# TO DO
# - Use temperature residuals for Haldanes in order to account for the influence of plasticity?
# - Temperature plots for context
# - Actual stats (mixed effects model, trait ~ collection temp, with experimental replicate as random effect)
# - ARR for % change to directly compare traits
# - Framework for quantifying the effects of within- and across-population variation in thermal limits to spatial patterns in vulnerability to warming. Comparing predictions based on 1) median, 2) overall CTmax vs. temp regression, 3) population variation in intercepts, 4) population variation in both slope and intercept
Site Characteristics
site_temps = full_data %>%
select(site, lat, season, doy, collection_temp, collection_salinity) %>%
distinct() %>%
filter(doy > 100)
Copepods were collected by surface tow from sites across the Western
Atlantic at several times throughout the year. The sites are shown
below. Temperatures at the time of collection were measured using a
manual thermometer. Across the entire set of collections, temperature
ranged from 12°C to 36°C.
coords = site_data %>%
select(site, long, lat) %>%
distinct()
site_map = map_data("world") %>%
filter(region %in% c("USA", "Canada")) %>%
ggplot() +
geom_polygon(aes(x = long, y = lat, group = group),
fill = "lightgrey") +
coord_map(xlim = c(-85,-60),
ylim = c(25, 48)) +
geom_point(data = coords,
mapping = aes(x = long, y = lat, colour = site),
size = 3) +
scale_colour_manual(values = site_cols) +
labs(x = "Longitude",
y = "Latitude") +
theme_matt(base_size = 16)
site_temp_plot = ggplot(site_temps, aes(x = doy, y = collection_temp, colour = site)) +
geom_line(linewidth = 2) +
geom_point(size = 5) +
scale_colour_manual(values = site_cols) +
labs(y = "Temperature (°C)",
x = "Day of the Year") +
theme_matt() +
theme(legend.position = "right")
ggarrange(site_map, site_temp_plot, common.legend = T, legend = "bottom")

Exact locations for the sites are provided here.
site_data %>%
arrange(lat) %>%
select("Site" = site, "Region" = region, "Lat" = lat, "Long" = long) %>%
knitr::kable(align = "c")
| Key Largo |
Florida |
25.28391 |
-80.33014 |
| Manatee River |
Florida |
27.50561 |
-82.57277 |
| Ft. Hamer |
Florida |
27.52488 |
-82.43101 |
| Tyler Cove |
Maryland |
38.35083 |
-76.22902 |
| Ganey’s Wharf |
Maryland |
38.80555 |
-75.90906 |
| Esker Point |
Connecticut |
41.32081 |
-72.00166 |
| Sawyer Park |
Maine |
43.90698 |
-69.87179 |
| St. Thomas de Kent Wharf |
New Brunswick |
46.44761 |
-64.63692 |
| Ritchie Wharf |
New Brunswick |
47.00481 |
-65.56291 |
Nested within each of the three regions (South, Central, and Northern
regions) are pairs of low and high salinity sites:
data.frame("Region" = c("South", "Central", "North"),
"Low Salinity" = c("Ft. Hamer", "Ganey's Wharf", "Ritchie Wharf"),
"High Salinity" = c("Manatee River", "Tyler Cove", "St. Thomas de Kent Wharf")) %>%
knitr::kable(align = "c")
| South |
Ft. Hamer |
Manatee River |
| Central |
Ganey’s Wharf |
Tyler Cove |
| North |
Ritchie Wharf |
St. Thomas de Kent Wharf |
There are fairly well-established divergences between high salinity
and low salinity populations of Acartia tonsa. These sets of
geographically proximate but isolated populations provide independent
comparisons of the effects of seasonality. Shown here are the collection
conditions for these pairs of sites. Temperature was typically similar
across the pairs within each collection, while salinity differences were
fairly stable across collections.
season_cols = c("early" = "grey75",
"peak" = "grey50",
"late" = "grey25")
sal_regions = data.frame(region = rep(c("South", "Central", "North"), each = 2),
site = c("Ft. Hamer", "Manatee River",
"Ganey's Wharf", "Tyler Cove",
"Ritchie Wharf", "St. Thomas de Kent Wharf"),
salinity = c("low", "high"))
sal_comps = full_data %>%
filter(site %in% sal_regions$site) %>%
inner_join(sal_regions, by = c("site")) %>%
select( region = region.y, site, salinity, season, doy, collection_temp, collection_salinity,
size, ctmax, warming_tol) %>%
mutate(salinity = fct_relevel(salinity, "low", "high"),
region = fct_relevel(region, "South", "Central", "North"))
sal_comp_temps = sal_comps %>%
select(salinity, season, region, collection_temp, collection_salinity) %>%
distinct() %>%
ggplot(aes(x = salinity, y = collection_temp, colour = season, group = season)) +
facet_wrap(region~.) +
geom_line(linewidth = 1.5) +
geom_point(size = 4) +
scale_colour_manual(values = season_cols) +
labs(y = "Collection Temp. (°C)",
x = "") +
theme_matt_facets(base_size = 14)
sal_comp_sal = sal_comps %>%
select(salinity, season, region, collection_temp, collection_salinity) %>%
distinct() %>%
ggplot(aes(x = salinity, y = collection_salinity, colour = season, group = season)) +
facet_wrap(region~.) +
geom_line(linewidth = 1.5) +
geom_point(size = 4) +
scale_colour_manual(values = season_cols) +
labs(y = "Collection Salinity (psu)",
x = "Salinity") +
theme_matt_facets(base_size = 14)
ggarrange(sal_comp_temps, sal_comp_sal, nrow = 2, common.legend = T, legend = "right")

# sal_comps %>%
# select(site, salinity, season, region, collection_temp, collection_salinity) %>%
# distinct() %>%
# ggplot(aes(x = collection_salinity, y = collection_temp, colour = site)) +
# facet_grid(region~.) +
# geom_point(size = 4) +
# #stat_ellipse() +
# #geom_path(arrow = arrow(length = unit(0.1, "inches"), type = "closed")) +
# scale_colour_manual(values = site_cols) +
# theme_matt_facets(base_size = 14)
The latitudinal gradient covers a wide range of seasonality. Shown
below is the temperature range. While based on collection temperatures,
and therefore an underestimate of the total seasonal range of
temperatures, these patterns are representative of the expected
latitudinal gradient in seasonality.
site_temps %>%
group_by(site, lat) %>%
summarise(temp_range = max(collection_temp) - min(collection_temp)) %>%
ggplot(aes(x = lat, y = temp_range)) +
geom_point(aes(colour = site),
size = 3) +
scale_color_manual(values = site_cols) +
labs(x = "Latitude",
y = "Collection Temp. Range (°C)") +
theme_matt() +
theme(legend.position = "right")

Phenotypic Measurements
Critical Thermal Limits
A total of 396 individuals were examined. Critical thermal limits and
body size measurements were made before individuals were preserved in
ethanol. We excluded data for 6 individuals, detailed below. These
individuals had either very low CTmax or were, upon re-examination of
photographs, identified as juveniles instead of mature females. With
these individuals excluded, the full data set contains 390
phenotyped individuals.
excluded %>%
select(region, site, season, collection_temp, collection_salinity, replicate, tube, ctmax, size) %>%
knitr::kable(align = "c")
| Florida |
Manatee River |
peak |
34.0 |
29 |
2 |
6 |
38.45833 |
0.616 |
| Florida |
Manatee River |
peak |
34.0 |
29 |
2 |
7 |
38.23750 |
0.593 |
| Maryland |
Tyler Cove |
peak |
29.5 |
15 |
2 |
2 |
36.84375 |
0.614 |
| Connecticut |
Esker Point |
early |
22.5 |
30 |
2 |
3 |
30.02604 |
0.687 |
| Maine |
Sawyer Park |
peak |
22.0 |
30 |
1 |
4 |
30.81424 |
0.865 |
| New Brunswick |
St. Thomas de Kent Wharf |
late |
13.5 |
28 |
1 |
3 |
28.78299 |
1.039 |
Critical thermal maxima (CTmax) was measured using a custom setup.
The method uses a standard dynamic ramping assay to determine the
maximum temperature individuals could sustain normal functioning. This
differs from lethal temperatures, and indeed, all individuals observed
so far recovered following the assay.
Individuals were rested for one hour after collection before the
assay. During the assay, copepods were held in artificial seawater,
composed of bottled spring water and Instant Ocean salt mix adjusted to
match collection salinities. During the assay, several ‘control’
individuals were maintained in this solution at ambient temperatures
without the temperature ramp to ensure that there was no background
mortality. When sorting individuals from the plankton tow contents, they
were held in a 50:50 mix of 60 um filtered water from the collection
site and artificial seawater as an additional acclimation step.
Shown below are the measured CTmax values. Note: CTmax values for the
early season Key Largo copepods were collected at the end of February
2023 as part of a separate project. Body size values were not measured
during this project, nor were copepods individually preserved after the
experiments. These early season CTmax values are included as a point of
comparison. Individual measurements are shown in small points for each
collection. The large points indicate the median values for each
collection.
mean_ctmax = full_data %>%
group_by(site, season, doy, collection_temp) %>%
summarize(mean_ctmax = mean(ctmax),
median_ctmax = median(ctmax))
ggplot(full_data, aes(x = season, y = ctmax, colour = site)) +
geom_line(data = mean_ctmax,
aes(y = median_ctmax, group = site),
position = position_dodge(width = 0.4),
linewidth = 1) +
geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
dodge.width = 0.4),
alpha = 0.3) +
geom_point(data = mean_ctmax,
aes(y = median_ctmax),
position = position_dodge(width = 0.4),
size = 4) +
scale_colour_manual(values = site_cols) +
labs(y = "CTmax (°C)",
x = "Season") +
theme_matt() +
theme(legend.position = "right",
legend.title.align = 0.125)

The same data is shown below, plotted against day of the year instead
of season. This accounts for the variable timing of collections across
regions (e.g. - the compressed collections from the Northern sites to
accomodate the earlier onset of cold temperatures).
ggplot(filter(full_data, site != "Key Largo"), aes(x = doy, y = ctmax, colour = site)) +
geom_line(data = filter(mean_ctmax, site != "Key Largo"),
aes(y = median_ctmax, group = site),
position = position_dodge(width = 0.4),
linewidth = 1) +
geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
dodge.width = 0.4),
alpha = 0.3) +
geom_point(data = filter(mean_ctmax, site != "Key Largo"),
aes(y = median_ctmax),
position = position_dodge(width = 0.4),
size = 4) +
scale_colour_manual(values = site_cols) +
labs(y = "CTmax (°C)",
x = "Season") +
theme_matt() +
theme(legend.position = "right",
legend.title.align = 0.125)

CTmax data for each individual site is shown below, plotted against
day of the year. The grey line in each facet shows the collection
temperatures. Note that both axes vary across facets.
ggplot(full_data, aes(x = doy, y = ctmax, colour = site)) +
facet_wrap(.~site, scales = "free") +
geom_line(data = mean_ctmax,
aes(y = median_ctmax, group = site),
position = position_dodge(width = 0.4),
linewidth = 3, alpha = 0.5) +
geom_line(data = mean_ctmax,
aes(y = collection_temp, group = site),
position = position_dodge(width = 0.4),
linewidth = 2,
colour = "grey") +
geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
dodge.width = 0.4),
alpha = 0.8) +
# geom_point(data = mean_ctmax,
# aes(y = median_ctmax),
# position = position_dodge(width = 0.4),
# size = 4) +
scale_colour_manual(values = site_cols) +
labs(y = "CTmax (°C)",
x = "Day of Year") +
theme_matt() +
theme(legend.position = "none",
legend.title.align = 0.125)

Warming tolerance
Warming tolerance (the difference between thermal limits and
environmental temperatures) is a commonly used metric of climate
vulnerability. We calculated this as the difference between measured
CTmax values and the collection temperature. Smaller warming tolerance
values indicate that populations were nearer to their upper thermal
limits, and may therefore be more vulnerable to additional warming.
mean_wt = full_data %>%
group_by(site, season) %>%
summarize(mean_wt = mean(warming_tol),
median_wt = median(warming_tol))
ggplot(full_data, aes(x = season, y = warming_tol, colour = site)) +
geom_line(data = mean_wt,
aes(y = median_wt, group = site),
position = position_dodge(width = 0.4),
linewidth = 1) +
geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
dodge.width = 0.4),
alpha = 0.3) +
geom_point(data = mean_wt,
aes(y = median_wt),
position = position_dodge(width = 0.4),
size = 4) +
scale_colour_manual(values = site_cols) +
labs(y = "Warming Tolerance (°C)",
x = "Season") +
theme_matt() +
theme(legend.position = "right",
legend.title.align = 0.125)

Body Size
Following the CTmax assay, individuals were photographed for body
size measurements. Prosome lengths were measured from these photographs
using a scale micrometer and the software ImageJ. These measurements are
shown below. As before, large points indicate the median body size.
mean_size = full_data %>%
group_by(site, season, doy, collection_temp) %>%
summarize(mean_size = mean(size),
median_size = median(size))
ggplot(full_data, aes(x = season, y = size, colour = site)) +
geom_line(data = mean_size,
aes(y = median_size, group = site),
position = position_dodge(width = 0.4),
linewidth = 1) +
geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
dodge.width = 0.4),
alpha = 0.3) +
geom_point(data = mean_size,
aes(y = median_size),
position = position_dodge(width = 0.4),
size = 4) +
scale_colour_manual(values = site_cols) +
labs(y = "Prosome Length (mm)",
x = "Season") +
theme_matt() +
theme(legend.position = "right",
legend.title.align = 0.125)

ggplot(drop_na(full_data, size), aes(x = doy, y = size, colour = site)) +
geom_line(data = drop_na(mean_size, mean_size),
aes(y = median_size, group = site),
position = position_dodge(width = 0.4),
linewidth = 1) +
geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
dodge.width = 0.4),
alpha = 0.3) +
geom_point(data = drop_na(mean_size, mean_size),
aes(y = median_size),
position = position_dodge(width = 0.4),
size = 4) +
scale_colour_manual(values = site_cols) +
labs(y = "Prosome Length (mm)",
x = "Season") +
theme_matt() +
theme(legend.position = "right",
legend.title.align = 0.125)

ggplot(drop_na(full_data, size), aes(x = doy, y = size, colour = site)) +
facet_wrap(.~site) +
geom_line(data = drop_na(mean_size, mean_size),
aes(y = median_size, group = site),
position = position_dodge(width = 0.4),
linewidth = 3, alpha = 0.5) +
geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
dodge.width = 0.4),
alpha = 0.8) +
# geom_point(data = mean_ctmax,
# aes(y = median_ctmax),
# position = position_dodge(width = 0.4),
# size = 4) +
scale_colour_manual(values = site_cols) +
labs(y = "Prosome Length (mm)",
x = "Day of Year") +
theme_matt() +
theme(legend.position = "none",
legend.title.align = 0.125)

Salinity Pair Comparisons
The three pairs of salinity comparisons do not show any general
pattern, with variation dominated by seasonal changes.
sal_comp_ctmax_plot = sal_comps %>%
ggplot(aes(x = salinity, y = ctmax, colour = season, group = season)) +
facet_wrap(region~.) +
geom_point(size = 2,
position = position_dodge(width = 0.2)) +
#geom_line(size = 1.5) +
scale_colour_manual(values = season_cols) +
labs(y = "CTmax (°C)",
x = "") +
theme_matt_facets(base_size = 14)
sal_comp_size_plot = sal_comps %>%
ggplot(aes(x = salinity, y = size, colour = season, group = season)) +
facet_wrap(region~.) +
geom_point(size = 2,
position = position_dodge(width = 0.2)) +
#geom_line(size = 1.5) +
scale_colour_manual(values = season_cols) +
labs(y = "Prosome Length (mm)",
x = "") +
theme_matt_facets(base_size = 14)
ggarrange(sal_comp_ctmax_plot, sal_comp_size_plot, nrow = 2, common.legend = T, legend = "right")

###
sal_comp_ctmax.model = lm(ctmax ~ collection_temp, data = sal_comps)
# summary(ctmax_temp.model)
# car::Anova(ctmax_temp.model)
sal_comp_ctmax_resids = residuals(sal_comp_ctmax.model)
sal_comp_size.model = lm(size ~ collection_temp, data = sal_comps)
# summary(size_temp.model)
# car::Anova(size_temp.model)
sal_comp_size_resids = residuals(sal_comp_size.model)
sal_comp_ctmax_resid_plot = sal_comps %>%
mutate(ctmax_resids = sal_comp_ctmax_resids,
size_resids = sal_comp_size_resids) %>%
ggplot(aes(x = salinity, y = ctmax_resids, colour = season, group = season)) +
facet_wrap(region~.) +
geom_point(size = 2,
position = position_dodge(width = 0.5)) +
#geom_line(size = 1.5) +
scale_colour_manual(values = season_cols) +
labs(y = "CTmax \nResiduals",
x = "") +
theme_matt_facets(base_size = 14)
sal_comp_size_resid_plot = sal_comps %>%
mutate(ctmax_resids = sal_comp_ctmax_resids,
size_resids = sal_comp_size_resids) %>%
ggplot(aes(x = salinity, y = size_resids, colour = season, group = season)) +
facet_wrap(region~.) +
geom_point(size = 2,
position = position_dodge(width = 0.5)) +
#geom_line(size = 1.5) +
scale_colour_manual(values = season_cols) +
labs(y = "Prosome Length \nResiduals",
x = "") +
theme_matt_facets(base_size = 14)
#ggarrange(sal_comp_ctmax_resid_plot, sal_comp_size_resid_plot, nrow = 2, common.legend = T, legend = "right")
Trait Correlations
We expect that collections from warmer waters should yield copepods
with higher thermal limits and smaller body sizes. Our observations
largely fit this expectation, with strong increases in CTmax at higher
temperatures, and a general decrease in prosome lengths as temperature
increased.
ctmax_temp_plot = ggplot(full_data, aes(x = collection_temp, y = ctmax)) +
geom_smooth(method = "lm", se = T,
linewidth = 2,
colour = "grey") +
geom_point(aes(colour = site),
size = 2, alpha = 0.7) +
scale_colour_manual(values = site_cols) +
labs(y = "CTmax (°C)",
x = "Collection Temp. (°C)") +
theme_matt() +
theme(legend.position = "none")
size_temp_plot = ggplot(full_data, aes(x = collection_temp, y = size)) +
geom_smooth(method = "lm", se = T,
linewidth = 2,
colour = "grey") +
geom_point(aes(colour = site),
size = 2, alpha = 0.7) +
scale_colour_manual(values = site_cols) +
labs(y = "Prosome Length (mm)",
x = "Collection Temp. (°C)") +
theme_matt() +
theme(legend.position = "right")
wt_temp_plot = ggplot(full_data, aes(x = collection_temp, y = warming_tol)) +
geom_smooth(method = "lm", se = T,
linewidth = 2,
colour = "grey") +
geom_point(aes(colour = site),
size = 2, alpha = 0.7) +
scale_colour_manual(values = site_cols) +
labs(y = "Warming Tolerance (°C)",
x = "Collection Temp. (°C)") +
theme_matt() +
theme(legend.position = "right")
ggarrange(ctmax_temp_plot, wt_temp_plot, size_temp_plot, common.legend = T, legend = "bottom", nrow = 1)

Of particular interest is the relationship between prosome length and
CTmax. In many cases, larger body sizes are associated with cold
adaptation/acclimation. We may therefore see this pattern emerge across
populations or seasons. If populations contain a mix of cold- and
warm-adapted genotypes, however, we might also see this relationship
emerge within populations or even individual
collections. Shown below is the relationship between prosome length and
CTmax in our data set. Individual regression lines for each site are
also included - the dark grey lines in the background represent the
‘universal’ regression for that site, with individual colored regression
lines for each collection.
universal_size = full_data %>%
ggplot(aes(x = size, y = ctmax)) +
# geom_smooth(data = filter(full_data, ctmax > 31),
# aes(x = size, y = ctmax),
# method = "lm",
# colour = "grey60",
# se = F,
# linewidth = 2) +
geom_smooth(method = "lm", se = T,
linewidth = 2,
colour = "grey70") +
geom_point(aes(colour = site),
size = 2, alpha = 0.7) +
scale_colour_manual(values = site_cols) +
labs(y = "CTmax (°C)",
x = "") +
theme_matt(base_size = 14) +
theme(legend.position = "right",
axis.title.x = element_blank())
pop_size = full_data %>%
ggplot(aes(x = size, y = ctmax, colour = site, group = season)) +
facet_wrap(site~.) +
# geom_smooth(data = filter(full_data, ctmax > 31),
# aes(x = size, y = ctmax),
# method = "lm",
# colour = "grey60",
# se = F,
# linewidth = 2) +
geom_smooth(data = full_data,
aes(x = size, y = ctmax, group = site),
colour = "grey20", method = "lm", se = F) +
geom_point(size = 1.3, alpha = 0.3) +
geom_smooth(method = "lm", se = F,
linewidth = 1) +
scale_colour_manual(values = site_cols) +
scale_x_continuous(breaks = c(0.6, 0.8, 1)) +
labs(y = "CTmax (°C)",
x = "Prosome Length (mm)") +
theme_matt(base_size = 14) +
theme(legend.position = "right")
ggarrange(universal_size, pop_size, common.legend = T, legend = "none", nrow = 2)

This relationship may be affected by changes in temperature at each
site, however, which is controlled for here by examining the
relationship between CTmax and size residuals, acquired from regressions
of these traits against collection temperature. This substantially
reduces the strength of the apparent relationship, but there is still a
slightly negative overall relationship.
filtered_data = full_data %>%
drop_na(size, ctmax)
ctmax_temp.model = lm(ctmax ~ collection_temp + site, data = filtered_data)
ctmax_resids = residuals(ctmax_temp.model)
size_temp.model = lm(size ~ collection_temp + site, data = filtered_data)
size_resids = residuals(size_temp.model)
universal_resids = filtered_data %>%
mutate(ctmax_resids = ctmax_resids,
size_resids = size_resids)
all_resids = ggplot(universal_resids, aes(x = size_resids, y = ctmax_resids)) +
# geom_smooth(data = filter(full_data, ctmax > 31),
# aes(x = size, y = ctmax),
# method = "lm",
# colour = "grey60",
# se = F,
# linewidth = 2) +
geom_smooth(method = "lm", se = T,
linewidth = 2,
colour = "grey70") +
geom_point(aes(colour = site),
size = 2, alpha = 0.7) +
scale_colour_manual(values = site_cols) +
labs(y = "CTmax Residuals",
x = "") +
theme_matt(base_size = 14) +
theme(legend.position = "right",
axis.title.x = element_blank())
pop_resids = ggplot(universal_resids, aes(x = size_resids, y = ctmax_resids, colour = site, group = season)) +
facet_wrap(site~.) +
# geom_smooth(data = filter(full_data, ctmax > 31),
# aes(x = size, y = ctmax),
# method = "lm",
# colour = "grey60",
# se = F,
# linewidth = 2) +
geom_smooth(aes(x = size_resids, y = ctmax_resids, group = site),
colour = "grey20", method = "lm", se = F) +
geom_point(size = 1.3, alpha = 0.3) +
geom_smooth(method = "lm", se = F,
linewidth = 1) +
scale_colour_manual(values = site_cols) +
labs(y = "CTmax Residuals",
x = "Prosome Length Residuals") +
theme_matt(base_size = 14) +
theme(legend.position = "right")
ggarrange(all_resids, pop_resids, common.legend = T, legend = "none", nrow = 2)

To more formally test the relationships between CTmax, collection
temperature, and size, we used a linear mixed effects model, structured
as ctmax ~ collection_temp + size + (1|site). This examines
the effects of temperature and size on CTmax, with random intercepts for
each site. Both fixed effects have a significant effect on CTmax. The
overall effect of temperature suggests an increase in CTmax of 0.15°C
per °C increase in collection temperature (i.e. - an ARR value of 0.15),
while increasing body sizes decrease CTmax by 3.7°C per mm (or a
decrease of ~0.37°C per tenth of a mm, which is more biologically
realistic for A. tonsa). This ARR value is slightly lower than
observed for other copepod species, but well within the range of
previously observed values. The estimated effect of body size is, as
expected, similar to that from the residuals plot above.
ctmax.model = lme4::lmer(data = filtered_data,
ctmax ~ collection_temp + size + (1|site))
effects_summary = data.frame("Temperature" = unname(lme4::fixef(ctmax.model)["collection_temp"]),
"Size" = unname(lme4::fixef(ctmax.model)["size"]))
knitr::kable(effects_summary)
By extracting the conditional mode for the random effects, we can
also examine how thermal limits vary across sites beyond the influence
of collection temperatures and body sizes. Shown below are these values,
extracted from the linear mixed effects model. We can see that, similar
to what’s been observed in common garden experiments with A.
tonsa previously, copepods from southern sites had higher thermal
limits than those from northern sites. Interestingly, these population
effects indicate that low salinity sites tended to have lower thermal
limits than their paired high salinity site.
pop_effs = as.data.frame(lme4::ranef(ctmax.model)) %>%
select("site" = grp, "pop_eff" = condval, "sd" = condsd) %>%
inner_join(site_data, by = c("site")) %>%
mutate(site = fct_reorder(site, lat))
ggplot(pop_effs, aes(x = lat, y = pop_eff, colour = site)) +
geom_hline(yintercept = 0) +
geom_errorbar(aes(ymin = pop_eff - sd, ymax = pop_eff + sd),
width = 0.5, linewidth = 1) +
geom_point(size = 3) +
scale_colour_manual(values = site_cols) +
labs(x = "Latitude",
y = "Population Effect") +
theme_matt() +
theme(legend.position = "right")

Trait Variability
Shown below is the trait variation (ranges) for each site. Ranges are
calculated for each collection separately.
trait_ranges = full_data %>%
group_by(site, season, collection_temp, collection_salinity, doy, lat) %>%
summarise(mean_ctmax = mean(ctmax),
ctmax_range = max(ctmax) - min(ctmax),
ctmax_var = var(ctmax),
mean_size = mean(size),
size_range = max(size) - min(size),
size_var = var(size)) %>%
mutate(prop_ctmax_range = ctmax_range / mean_ctmax,
prop_size_range = size_range / mean_size)
ctmax_range_temp = ggplot(trait_ranges, aes(x = collection_temp, y = ctmax_range, colour = site)) +
geom_point(size = 3) +
scale_colour_manual(values = site_cols) +
labs(y = "CTmax Range (°C)",
x = "Collection Temp. (°C)") +
theme_matt() +
theme(legend.position = "right")
ctmax_var_temp = ggplot(trait_ranges, aes(x = collection_temp, y = ctmax_var, colour = site)) +
geom_point(size = 3) +
scale_colour_manual(values = site_cols) +
labs(y = "CTmax Range (°C)",
x = "Collection Temp. (°C)") +
theme_matt() +
theme(legend.position = "right")
size_range_temp = ggplot(trait_ranges, aes(x = collection_temp, y = size_range, colour = site)) +
geom_point(size = 3) +
scale_colour_manual(values = site_cols) +
labs(y = "Size Range (mm)",
x = "Collection Temp. (°C)") +
theme_matt() +
theme(legend.position = "right")
size_var_temp = ggplot(trait_ranges, aes(x = collection_temp, y = size_var, colour = site)) +
geom_point(size = 3) +
scale_colour_manual(values = site_cols) +
labs(y = "Size Range (mm)",
x = "Collection Temp. (°C)") +
theme_matt() +
theme(legend.position = "right")
ggarrange(ctmax_range_temp, size_range_temp, common.legend = T, legend = "bottom")

Changes in trait variance may be indicative of phenotypic selection.
If selection (as opposed to acclimation) are driving seasonal changes,
we may expect to see a reduction in variance in the peak samples
relative to the early season samples. Note that early season collection
temperatures this year were higher than expected, driven by fairly
strong heatwaves across the North Atlantic.
ggplot(trait_ranges, aes(x = season, y = ctmax_var, colour = site)) +
geom_line(aes(group = site),
linewidth = 1.5) +
geom_point(size = 3) +
scale_colour_manual(values = site_cols) +
labs(y = "CTmax Variance",
x = "Season") +
theme_matt() +
theme(legend.position = "right",
legend.title.align = 0.125)

Comparing rates of change (Haldanes)
Both CTmax and body size varied between sites and across seasons. It
can be difficult to directly compare these two traits. We take two
approaches to ease this comparison. Shown below is a comparison of the
slopes from the trait regressions against collection temperature for
each population, standardized by the standard deviation of the trait for
each population (across all collections). This presents change per
degree change in collection temperature in units of standard deviations
for both CTmax and body size.
adj_slopes = full_data %>%
group_by(site, lat) %>%
arrange(doy) %>%
filter(site != "Key Largo") %>%
summarize("ctmax_slope" = coef(lm(ctmax ~ collection_temp))["collection_temp"],
"mean_ctmax" = mean(ctmax),
"ctmax_sd" = sd(ctmax),
"size_slope" = coef(lm(size ~ collection_temp))["collection_temp"],
"mean_size" = mean(size),
"size_sd" = sd(size),
"temp_range" = max(collection_temp) - min(collection_temp)) %>%
drop_na() %>%
mutate(adj_ctmax_slope = ctmax_slope / ctmax_sd,
adj_size_slope = size_slope / size_sd) %>%
pivot_longer(cols = contains("_slope"),
names_to = "slope_type",
values_to = "slope")
# ggplot(adj_slopes, aes(x = lat, y = temp_range)) +
# geom_point() +
# theme_matt()
ggplot(filter(adj_slopes, str_detect(slope_type, "adj_")), aes(x = slope_type, y = abs(slope),
group = site, colour = site)) +
geom_hline(yintercept = 0) +
geom_line(linewidth = 1) +
scale_colour_manual(values = site_cols) +
labs(x = "",
y = "Slope (absolute value)") +
theme_matt() +
theme(legend.position = "right",
axis.text.x = element_text(angle = 300, hjust = 0, vjust = 0.5))

Haldanes are a similar unit, representing change in units of standard
deviations per generation. This can be a useful metric for comparing
across traits, especially as the number of generations covered by our
sampling period likely varies across populations. The calculation of
haldanes is taken from Hendry and Kinnison (1999), which in turn is
based on work from Gingerich (1993). We estimated the number of
generations passed between collections using the empirical relationship
between temperature and development time for Acartia tonsa from
Leandro et al. (2006). For initial estimates, we used a temperature
halfway between what was observed during collection. Changes were
examined for each pair of collections (early to peak, and peak to
late).
Shown below is a comparison of the estimated haldane values for CTmax
and body size, separated by season. Keep in mind that while this metric
accounts for differences in the number of generations between
collections, it does not directly account for differences in
temperature, leading to inflated values in the “peak to late”
comparisons, which typically covered a larger range of temperatures.
early_peak = full_data %>%
filter(season %in% c("early", "peak")) %>%
mutate(season = if_else(season == "early", "one", "two")) %>%
group_by(site) %>%
mutate(ctmax_sd_p = sd(ctmax),
size_sd_p = sd(size),
temp_change = max(collection_temp) - min(collection_temp),
avg_temp = (max(collection_temp) + min(collection_temp)) / 2,
days_passed = max(doy) - min(doy)) %>%
select(site, lat, season,
ctmax_sd_p, size_sd_p,
temp_change, avg_temp, days_passed,
ctmax, size) %>%
group_by(site, lat, season,
ctmax_sd_p, size_sd_p,
temp_change, avg_temp, days_passed) %>%
summarize(ctmax = mean(ctmax),
size = mean(size)) %>%
pivot_wider(id_cols = c(site, lat, ctmax_sd_p, size_sd_p,
temp_change, avg_temp, days_passed),
names_from = season,
values_from = c(ctmax, size)) %>%
mutate(season = "early_to_peak") %>%
drop_na()
peak_late = full_data %>%
filter(season %in% c("peak", "late")) %>%
mutate(season = if_else(season == "peak", "one", "two")) %>%
group_by(site) %>%
mutate(ctmax_sd_p = sd(ctmax),
size_sd_p = sd(size),
temp_change = last(collection_temp) - first(collection_temp),
avg_temp = (max(collection_temp) + min(collection_temp)) / 2,
days_passed = max(doy) - min(doy)) %>%
select(site, lat, season, ctmax_sd_p, size_sd_p,
temp_change, avg_temp, days_passed,
ctmax, size) %>%
group_by(site, lat, season, ctmax_sd_p, size_sd_p,
temp_change, avg_temp, days_passed) %>%
summarize(ctmax = mean(ctmax),
size = mean(size)) %>%
pivot_wider(id_cols = c(site, lat, ctmax_sd_p, size_sd_p,
temp_change, avg_temp, days_passed),
names_from = season,
values_from = c(ctmax, size)) %>%
mutate(season = "peak_to_late") %>%
drop_na()
calc_halds = function(x1, x2, sd_p, g){
((x2 / sd_p) - (x1 / sd_p)) / g
}
haldanes = bind_rows(early_peak, peak_late) %>%
mutate("gen_time" = 5490*(avg_temp + 1)^-2.05,
"gens" = floor(days_passed / gen_time),
"ctmax_haldanes" = calc_halds(x2 = ctmax_two, x1 = ctmax_one,
sd_p = ctmax_sd_p, g = gens),
"size_haldanes" = calc_halds(x2 = size_two, x1 = size_one,
sd_p = size_sd_p, g = gens))
haldanes %>%
ungroup() %>%
select(site, temp_change, season, ctmax_haldanes, size_haldanes) %>%
pivot_longer(cols = c(ctmax_haldanes, size_haldanes),
names_to = c("type", NA),
names_sep = "_",
values_to = "haldanes") %>%
ggplot(aes(x = type, y = haldanes, group = site, colour = site)) +
facet_wrap(season~.) +
geom_hline(yintercept = 0) +
geom_line(aes(linewidth = desc(temp_change))) +
scale_colour_manual(values = site_cols) +
labs(x = "Trait",
y = "Haldanes",
linewidth = "Temp. Change") +
theme_matt_facets()

Shown below are the haldane values plotted against latitude. Note
that even though large changes in temperature occured between peak and
late samples in the Chesapeake, the change in haldanes is relatively
small, while in the Northern populations, changes are larger, though
more variable.
ctmax_haldanes = ggplot(haldanes, aes(x = lat, y = ctmax_haldanes, colour = site, shape = season)) +
geom_hline(yintercept = 0) +
geom_point(size = 3) +
scale_colour_manual(values = site_cols) +
labs(x = "Latitude",
y = "Change in CTmax (haldanes)") +
theme_matt_facets()
size_haldanes = ggplot(haldanes, aes(x = lat, y = size_haldanes, colour = site, shape = season)) +
geom_hline(yintercept = 0) +
geom_point(size = 3) +
scale_colour_manual(values = site_cols) +
labs(x = "Latitude",
y = "Change in Size (haldanes)") +
theme_matt_facets()
ggarrange(ctmax_haldanes, size_haldanes, common.legend = T, legend = "right", nrow = 2)

Next Steps
After phenotyping, each individual was preserved in 95% ethanol.
Individual DNA libraries will be prepared using Twist Bio 96-plex prep
kits, then sequenced on an Illumina NovaSeq X Plus. Using the
low-coverage whole genome sequences, we will examine seasonal patterns
in allele frequency change, and compare these fine scale temporal
patterns with the larger latitudinal patterns in allele frequency to
determine whether the same alleles driving rapid seasonal adaptation are
in play over larger spatial (and longer temporal) scales.
Misc. Details
ggplot(temp_record, aes(x = minute_passed, y = temp_C, group = factor(run))) +
geom_abline(slope = 0.3, intercept = mean(temp_record[temp_record$minute_interval == 0, 8])) +
geom_abline(slope = 0.1, intercept = mean(temp_record[temp_record$minute_interval == 0, 8])) +
geom_line(linewidth = 0.2, alpha = 0.8) +
geom_point(data = full_data,
aes(x = time, y = ctmax + 0.4),
size = 2,
shape = 25) +
labs(x = "Time passed (minutes)",
y = "Temperature (degrees C)",
fill = "Trial Number") +
guides(colour = "none") +
theme_matt(base_size = 16) +
theme(legend.position = "right")

ramp_record2 = ramp_record %>%
group_by(run, minute_interval) %>%
summarise(mean_ramp = mean(ramp_per_minute)) %>%
ungroup()
ggplot(ramp_record2, aes(x = minute_interval, y = mean_ramp)) +
geom_hline(yintercept = 0.3) +
geom_hline(yintercept = 0.1) +
#geom_point() +
geom_hex(bins = 30) +
ylim(0, 0.35) +
labs(y = "Ramp Rate (deg. C / min.)",
x = "Time into run (minute)") +
theme_matt(base_size = 16)

full_data %>%
drop_na(replicate) %>%
ggplot(aes(x = factor(replicate), y = ctmax, group = site)) +
facet_grid(site~season, scales = "free_y") +
geom_point(position = position_jitter(width = 0.1, height = 0),
alpha = 0.4,
colour = "grey30") +
geom_smooth(method = "lm", colour = "black") +
labs(x = "Replicate",
y = "CTmax") +
theme_matt_facets()

ggplot(haldanes, aes(x = lat, y = gens, colour = site, shape = season)) +
geom_hline(yintercept = 0) +
geom_point(size = 5) +
scale_colour_manual(values = site_cols) +
labs(x = "Latitude",
y = "Generations between \ncollections") +
scale_y_continuous(breaks = seq(from = 0, to = 11, by = 2)) +
theme_matt() +
theme(legend.position = "right")

LS0tCnRpdGxlOiAiQ29tcGFyaW5nIHNlYXNvbmFsIGFuZCBsYXRpdHVkaW5hbCBwYXR0ZXJucyBpbiB0aGVybWFsIGFkYXB0YXRpb24iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgICAgICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICAgICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgICAgICB0b2M6IHRydWUKICAgICAgICAgIHRvY19mbG9hdDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgICAgICAgIGh0bWxfcHJldmlldzogZmFsc2UKICAgICAgICAgIHRvYzogdHJ1ZQogICAgICAgICAgdG9jX2RlcHRoOiAzCi0tLQoKYGBge3J9CiMgVE8gRE8gCgojIC0gVXNlIHRlbXBlcmF0dXJlIHJlc2lkdWFscyBmb3IgSGFsZGFuZXMgaW4gb3JkZXIgdG8gYWNjb3VudCBmb3IgdGhlIGluZmx1ZW5jZSBvZiBwbGFzdGljaXR5PyAKIyAtIFRlbXBlcmF0dXJlIHBsb3RzIGZvciBjb250ZXh0IAojIC0gQWN0dWFsIHN0YXRzIChtaXhlZCBlZmZlY3RzIG1vZGVsLCB0cmFpdCB+IGNvbGxlY3Rpb24gdGVtcCwgd2l0aCBleHBlcmltZW50YWwgcmVwbGljYXRlIGFzIHJhbmRvbSBlZmZlY3QpCiMgLSBBUlIgZm9yICUgY2hhbmdlIHRvIGRpcmVjdGx5IGNvbXBhcmUgdHJhaXRzIAojIC0gRnJhbWV3b3JrIGZvciBxdWFudGlmeWluZyB0aGUgZWZmZWN0cyBvZiB3aXRoaW4tIGFuZCBhY3Jvc3MtcG9wdWxhdGlvbiB2YXJpYXRpb24gaW4gdGhlcm1hbCBsaW1pdHMgdG8gc3BhdGlhbCBwYXR0ZXJucyBpbiB2dWxuZXJhYmlsaXR5IHRvIHdhcm1pbmcuIENvbXBhcmluZyBwcmVkaWN0aW9ucyBiYXNlZCBvbiAxKSBtZWRpYW4sIDIpIG92ZXJhbGwgQ1RtYXggdnMuIHRlbXAgcmVncmVzc2lvbiwgMykgcG9wdWxhdGlvbiB2YXJpYXRpb24gaW4gaW50ZXJjZXB0cywgNCkgcG9wdWxhdGlvbiB2YXJpYXRpb24gaW4gYm90aCBzbG9wZSBhbmQgaW50ZXJjZXB0CmBgYAoKCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1ULCBtZXNzYWdlID0gRiwgd2FybmluZyA9IEYsIGVjaG8gPSBGfQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBrbml0cjo6aXNfaHRtbF9vdXRwdXQoKSwKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwKICBmaWcucGF0aCA9ICIuLi9GaWd1cmVzL21hcmtkb3duLyIsCiAgZGV2ID0gYygicG5nIiwgInBkZiIpLAogIG1lc3NhZ2UgPSBGQUxTRSwKICB3YXJuaW5nID0gRkFMU0UsCiAgY29sbGFwc2UgPSBUCikKCnRoZW1lX21hdHQgPSBmdW5jdGlvbihiYXNlX3NpemUgPSAxOCwKICAgICAgICAgICAgICAgICAgICAgIGRhcmtfdGV4dCA9ICJncmV5MjAiKXsKICBtaWRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzJdCiAgbGlnaHRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzNdCiAgCiAgdGhlbWVfcHVicihiYXNlX2ZhbWlseT0ic2FucyIpICUrcmVwbGFjZSUgCiAgICB0aGVtZSgKICAgICAgcGFuZWwuYmFja2dyb3VuZCAgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLCAKICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwgCiAgICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwKICAgICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksCiAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gbWlkX3RleHQsIGxpbmVoZWlnaHQgPSAxLjEpLAogICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS41LAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBkYXJrX3RleHQpLAogICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IG1pZF90ZXh0KSwKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMywgMCwgMCwgMCksICJtbSIpKSwKICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMCwgNSwgMCwgMCksICJtbSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuZ2xlID0gOTApLAogICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPWJhc2Vfc2l6ZSAqIDAuOSksCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMC45LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2UgPSAiYm9sZCIpLAogICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLjI1LCAwLjI1LCAwLjI1LCAwLjI1LCJjbSIpCiAgICApCn0KCnRoZW1lX21hdHRfZmFjZXRzID0gZnVuY3Rpb24oYmFzZV9zaXplID0gMTgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGFya190ZXh0ID0gImdyZXkyMCIpewogIG1pZF90ZXh0IDwtICBtb25vY2hyb21lUjo6Z2VuZXJhdGVfcGFsZXR0ZShkYXJrX3RleHQsICJnb19saWdodGVyIiwgbl9jb2xvdXJzID0gNSlbMl0KICBsaWdodF90ZXh0IDwtICBtb25vY2hyb21lUjo6Z2VuZXJhdGVfcGFsZXR0ZShkYXJrX3RleHQsICJnb19saWdodGVyIiwgbl9jb2xvdXJzID0gNSlbM10KICAKICB0aGVtZV9idyhiYXNlX2ZhbWlseT0ic2FucyIpICUrcmVwbGFjZSUgCiAgICB0aGVtZSgKICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGFuZWwuYmFja2dyb3VuZCAgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLCAKICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwgCiAgICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwKICAgICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksCiAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gbWlkX3RleHQsIGxpbmVoZWlnaHQgPSAxLjEpLAogICAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSksCiAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IGRhcmtfdGV4dCksCiAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gbWlkX3RleHQpLAogICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDEuMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygzLCAwLCAwLCAwKSwgIm1tIikpLAogICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDEuMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygwLCA1LCAwLCAwKSwgIm1tIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5nbGUgPSA5MCksCiAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9YmFzZV9zaXplICogMC45KSwKICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAwLjksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjZSA9ICJib2xkIiksCiAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDAuMjUsIDAuMjUsIDAuMjUsIDAuMjUsImNtIikKICAgICkKfQoKc2l0ZV9jb2xzID0gYygiS2V5IExhcmdvIiA9ICJpbmRpYW5yZWQ0IiwgCiAgICAgICAgICAgICAgIk1hbmF0ZWUgUml2ZXIiID0gImNvcmFsIiwgCiAgICAgICAgICAgICAgIkZ0LiBIYW1lciIgPSAiY29yYWwzIiwKICAgICAgICAgICAgICAiVHlsZXIgQ292ZSIgPSAiZ29sZGVucm9kMSIsCiAgICAgICAgICAgICAgIkdhbmV5J3MgV2hhcmYiID0gImRhcmtnb2xkZW5yb2QzIiwgCiAgICAgICAgICAgICAgIkVza2VyIFBvaW50IiA9ICJkYXJrc2VhZ3JlZW4zIiwKICAgICAgICAgICAgICAiU2F3eWVyIFBhcmsiID0gInBhbGVncmVlbjQiLCAKICAgICAgICAgICAgICAiU3QuIFRob21hcyBkZSBLZW50IFdoYXJmIiA9ICJzdGVlbGJsdWUyIiwKICAgICAgICAgICAgICAiUml0Y2hpZSBXaGFyZiIgPSAic3RlZWxibHVlNCIpCmBgYAoKIyMgU2l0ZSBDaGFyYWN0ZXJpc3RpY3MKCmBgYHtyfQpzaXRlX3RlbXBzID0gZnVsbF9kYXRhICU+JSAKICBzZWxlY3Qoc2l0ZSwgbGF0LCBzZWFzb24sIGRveSwgY29sbGVjdGlvbl90ZW1wLCBjb2xsZWN0aW9uX3NhbGluaXR5KSAlPiUgIAogIGRpc3RpbmN0KCkgJT4lIAogIGZpbHRlcihkb3kgPiAxMDApIApgYGAKCkNvcGVwb2RzIHdlcmUgY29sbGVjdGVkIGJ5IHN1cmZhY2UgdG93IGZyb20gc2l0ZXMgYWNyb3NzIHRoZSBXZXN0ZXJuIEF0bGFudGljIGF0IHNldmVyYWwgdGltZXMgdGhyb3VnaG91dCB0aGUgeWVhci4gVGhlIHNpdGVzIGFyZSBzaG93biBiZWxvdy4gVGVtcGVyYXR1cmVzIGF0IHRoZSB0aW1lIG9mIGNvbGxlY3Rpb24gd2VyZSBtZWFzdXJlZCB1c2luZyBhIG1hbnVhbCB0aGVybW9tZXRlci4gQWNyb3NzIHRoZSBlbnRpcmUgc2V0IG9mIGNvbGxlY3Rpb25zLCB0ZW1wZXJhdHVyZSByYW5nZWQgZnJvbSBgciBtaW4oc2l0ZV90ZW1wcyRjb2xsZWN0aW9uX3RlbXApYMKwQyB0byBgciBtYXgoc2l0ZV90ZW1wcyRjb2xsZWN0aW9uX3RlbXApYMKwQy4KCmBgYHtyIHNpdGUtY2hhcnMsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02fQpjb29yZHMgPSBzaXRlX2RhdGEgJT4lCiAgc2VsZWN0KHNpdGUsIGxvbmcsIGxhdCkgJT4lCiAgZGlzdGluY3QoKQoKc2l0ZV9tYXAgPSBtYXBfZGF0YSgid29ybGQiKSAlPiUgCiAgZmlsdGVyKHJlZ2lvbiAlaW4lIGMoIlVTQSIsICJDYW5hZGEiKSkgJT4lIAogIGdncGxvdCgpICsgCiAgZ2VvbV9wb2x5Z29uKGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksCiAgICAgICAgICAgICAgIGZpbGwgPSAibGlnaHRncmV5IikgKyAKICBjb29yZF9tYXAoeGxpbSA9IGMoLTg1LC02MCksCiAgICAgICAgICAgIHlsaW0gPSBjKDI1LCA0OCkpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gY29vcmRzLAogICAgICAgICAgICAgbWFwcGluZyA9IGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgY29sb3VyID0gc2l0ZSksCiAgICAgICAgICAgICBzaXplID0gMykgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeCA9ICJMb25naXR1ZGUiLCAKICAgICAgIHkgPSAiTGF0aXR1ZGUiKSArIAogIHRoZW1lX21hdHQoYmFzZV9zaXplID0gMTYpCgpzaXRlX3RlbXBfcGxvdCA9IGdncGxvdChzaXRlX3RlbXBzLCBhZXMoeCA9IGRveSwgeSA9IGNvbGxlY3Rpb25fdGVtcCwgY29sb3VyID0gc2l0ZSkpICsgCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDIpICsgCiAgZ2VvbV9wb2ludChzaXplID0gNSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiAgICAgICB4ID0gIkRheSBvZiB0aGUgWWVhciIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKZ2dhcnJhbmdlKHNpdGVfbWFwLCBzaXRlX3RlbXBfcGxvdCwgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJib3R0b20iKQpgYGAKCkV4YWN0IGxvY2F0aW9ucyBmb3IgdGhlIHNpdGVzIGFyZSBwcm92aWRlZCBoZXJlLiAKCmBgYHtyIHNpdGUtdGFibGV9CnNpdGVfZGF0YSAlPiUgIAogIGFycmFuZ2UobGF0KSAlPiUgIAogIHNlbGVjdCgiU2l0ZSIgPSBzaXRlLCAiUmVnaW9uIiA9IHJlZ2lvbiwgIkxhdCIgPSBsYXQsICJMb25nIiA9IGxvbmcpICU+JSAKICBrbml0cjo6a2FibGUoYWxpZ24gPSAiYyIpCmBgYAoKTmVzdGVkIHdpdGhpbiBlYWNoIG9mIHRoZSB0aHJlZSByZWdpb25zIChTb3V0aCwgQ2VudHJhbCwgYW5kIE5vcnRoZXJuIHJlZ2lvbnMpIGFyZSBwYWlycyBvZiBsb3cgYW5kIGhpZ2ggc2FsaW5pdHkgc2l0ZXM6ICAgIAoKYGBge3Igc2FsLXRhYmxlfQpkYXRhLmZyYW1lKCJSZWdpb24iID0gYygiU291dGgiLCAiQ2VudHJhbCIsICJOb3J0aCIpLAogICAgICAgICAgICJMb3cgU2FsaW5pdHkiID0gYygiRnQuIEhhbWVyIiwgIkdhbmV5J3MgV2hhcmYiLCAiUml0Y2hpZSBXaGFyZiIpLAogICAgICAgICAgICJIaWdoIFNhbGluaXR5IiA9IGMoIk1hbmF0ZWUgUml2ZXIiLCAiVHlsZXIgQ292ZSIsICJTdC4gVGhvbWFzIGRlIEtlbnQgV2hhcmYiKSkgJT4lIAogIGtuaXRyOjprYWJsZShhbGlnbiA9ICJjIikKYGBgCgpcIAoKVGhlcmUgYXJlIGZhaXJseSB3ZWxsLWVzdGFibGlzaGVkIGRpdmVyZ2VuY2VzIGJldHdlZW4gaGlnaCBzYWxpbml0eSBhbmQgbG93IHNhbGluaXR5IHBvcHVsYXRpb25zIG9mICpBY2FydGlhIHRvbnNhKi4gVGhlc2Ugc2V0cyBvZiBnZW9ncmFwaGljYWxseSBwcm94aW1hdGUgYnV0IGlzb2xhdGVkIHBvcHVsYXRpb25zIHByb3ZpZGUgaW5kZXBlbmRlbnQgY29tcGFyaXNvbnMgb2YgdGhlIGVmZmVjdHMgb2Ygc2Vhc29uYWxpdHkuIFNob3duIGhlcmUgYXJlIHRoZSBjb2xsZWN0aW9uIGNvbmRpdGlvbnMgZm9yIHRoZXNlIHBhaXJzIG9mIHNpdGVzLiBUZW1wZXJhdHVyZSB3YXMgdHlwaWNhbGx5IHNpbWlsYXIgYWNyb3NzIHRoZSBwYWlycyB3aXRoaW4gZWFjaCBjb2xsZWN0aW9uLCB3aGlsZSBzYWxpbml0eSBkaWZmZXJlbmNlcyB3ZXJlIGZhaXJseSBzdGFibGUgYWNyb3NzIGNvbGxlY3Rpb25zLiAKCmBgYHtyIHNlYXNvbi1zYWwtY29tcHMsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTh9CnNlYXNvbl9jb2xzID0gYygiZWFybHkiID0gImdyZXk3NSIsIAogICAgICAgICAgICAgICAgInBlYWsiID0gImdyZXk1MCIsIAogICAgICAgICAgICAgICAgImxhdGUiID0gImdyZXkyNSIpCgpzYWxfcmVnaW9ucyA9IGRhdGEuZnJhbWUocmVnaW9uID0gcmVwKGMoIlNvdXRoIiwgIkNlbnRyYWwiLCAiTm9ydGgiKSwgZWFjaCA9IDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHNpdGUgPSBjKCJGdC4gSGFtZXIiLCAiTWFuYXRlZSBSaXZlciIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdhbmV5J3MgV2hhcmYiLCAiVHlsZXIgQ292ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJpdGNoaWUgV2hhcmYiLCAiU3QuIFRob21hcyBkZSBLZW50IFdoYXJmIiksCiAgICAgICAgICAgICAgICAgICAgICAgICBzYWxpbml0eSA9IGMoImxvdyIsICJoaWdoIikpCgpzYWxfY29tcHMgPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzaXRlICVpbiUgc2FsX3JlZ2lvbnMkc2l0ZSkgJT4lIAogIGlubmVyX2pvaW4oc2FsX3JlZ2lvbnMsIGJ5ID0gYygic2l0ZSIpKSAlPiUgCiAgc2VsZWN0KCByZWdpb24gPSByZWdpb24ueSwgc2l0ZSwgc2FsaW5pdHksIHNlYXNvbiwgZG95LCBjb2xsZWN0aW9uX3RlbXAsIGNvbGxlY3Rpb25fc2FsaW5pdHksCiAgICAgICAgICBzaXplLCBjdG1heCwgd2FybWluZ190b2wpICU+JSAKICBtdXRhdGUoc2FsaW5pdHkgPSBmY3RfcmVsZXZlbChzYWxpbml0eSwgImxvdyIsICJoaWdoIiksCiAgICAgICAgIHJlZ2lvbiA9IGZjdF9yZWxldmVsKHJlZ2lvbiwgIlNvdXRoIiwgIkNlbnRyYWwiLCAiTm9ydGgiKSkKCnNhbF9jb21wX3RlbXBzID0gc2FsX2NvbXBzICU+JSAgCiAgc2VsZWN0KHNhbGluaXR5LCBzZWFzb24sIHJlZ2lvbiwgY29sbGVjdGlvbl90ZW1wLCBjb2xsZWN0aW9uX3NhbGluaXR5KSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc2FsaW5pdHksIHkgPSBjb2xsZWN0aW9uX3RlbXAsIGNvbG91ciA9IHNlYXNvbiwgZ3JvdXAgPSBzZWFzb24pKSArIAogIGZhY2V0X3dyYXAocmVnaW9ufi4pICsgCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDEuNSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2Vhc29uX2NvbHMpICsgCiAgbGFicyh5ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiLAogICAgICAgeCA9ICIiKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKGJhc2Vfc2l6ZSA9IDE0KQoKc2FsX2NvbXBfc2FsID0gc2FsX2NvbXBzICU+JSAgCiAgc2VsZWN0KHNhbGluaXR5LCBzZWFzb24sIHJlZ2lvbiwgY29sbGVjdGlvbl90ZW1wLCBjb2xsZWN0aW9uX3NhbGluaXR5KSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc2FsaW5pdHksIHkgPSBjb2xsZWN0aW9uX3NhbGluaXR5LCBjb2xvdXIgPSBzZWFzb24sIGdyb3VwID0gc2Vhc29uKSkgKyAKICBmYWNldF93cmFwKHJlZ2lvbn4uKSArIAogIGdlb21fbGluZShsaW5ld2lkdGggPSAxLjUpICsgCiAgZ2VvbV9wb2ludChzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNlYXNvbl9jb2xzKSArIAogIGxhYnMoeSA9ICJDb2xsZWN0aW9uIFNhbGluaXR5IChwc3UpIiwKICAgICAgIHggPSAiU2FsaW5pdHkiKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKGJhc2Vfc2l6ZSA9IDE0KQoKZ2dhcnJhbmdlKHNhbF9jb21wX3RlbXBzLCBzYWxfY29tcF9zYWwsIG5yb3cgPSAyLCBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gInJpZ2h0IikKCiMgc2FsX2NvbXBzICU+JSAgCiMgICBzZWxlY3Qoc2l0ZSwgc2FsaW5pdHksIHNlYXNvbiwgcmVnaW9uLCBjb2xsZWN0aW9uX3RlbXAsIGNvbGxlY3Rpb25fc2FsaW5pdHkpICU+JSAKIyAgIGRpc3RpbmN0KCkgJT4lIAojICAgZ2dwbG90KGFlcyh4ID0gY29sbGVjdGlvbl9zYWxpbml0eSwgeSA9IGNvbGxlY3Rpb25fdGVtcCwgY29sb3VyID0gc2l0ZSkpICsgCiMgICBmYWNldF9ncmlkKHJlZ2lvbn4uKSArIAojICAgZ2VvbV9wb2ludChzaXplID0gNCkgKyAKIyAgICNzdGF0X2VsbGlwc2UoKSArCiMgICAjZ2VvbV9wYXRoKGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgwLjEsICJpbmNoZXMiKSwgdHlwZSA9ICJjbG9zZWQiKSkgKyAKIyAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAojICAgdGhlbWVfbWF0dF9mYWNldHMoYmFzZV9zaXplID0gMTQpCmBgYAoKVGhlIGxhdGl0dWRpbmFsIGdyYWRpZW50IGNvdmVycyBhIHdpZGUgcmFuZ2Ugb2Ygc2Vhc29uYWxpdHkuIFNob3duIGJlbG93IGlzIHRoZSB0ZW1wZXJhdHVyZSByYW5nZS4gV2hpbGUgYmFzZWQgb24gY29sbGVjdGlvbiB0ZW1wZXJhdHVyZXMsIGFuZCB0aGVyZWZvcmUgYW4gdW5kZXJlc3RpbWF0ZSBvZiB0aGUgdG90YWwgc2Vhc29uYWwgcmFuZ2Ugb2YgdGVtcGVyYXR1cmVzLCB0aGVzZSBwYXR0ZXJucyBhcmUgcmVwcmVzZW50YXRpdmUgb2YgdGhlIGV4cGVjdGVkIGxhdGl0dWRpbmFsIGdyYWRpZW50IGluIHNlYXNvbmFsaXR5LiAKCmBgYHtyIGxhdC10ZW1wLXJhbmdlLXBsb3QsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTV9CnNpdGVfdGVtcHMgJT4lIAogIGdyb3VwX2J5KHNpdGUsIGxhdCkgJT4lICAKICBzdW1tYXJpc2UodGVtcF9yYW5nZSA9IG1heChjb2xsZWN0aW9uX3RlbXApIC0gbWluKGNvbGxlY3Rpb25fdGVtcCkpICU+JSAgCiAgZ2dwbG90KGFlcyh4ID0gbGF0LCB5ID0gdGVtcF9yYW5nZSkpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gc2l0ZSksCiAgICAgICAgICAgICBzaXplID0gMykgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeCA9ICJMYXRpdHVkZSIsIAogICAgICAgeSA9ICJDb2xsZWN0aW9uIFRlbXAuIFJhbmdlICjCsEMpIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCgojIyBQaGVub3R5cGljIE1lYXN1cmVtZW50cyAKCiMjIyBDcml0aWNhbCBUaGVybWFsIExpbWl0cwoKQSB0b3RhbCBvZiBgciBkaW0oYWxsX2RhdGEpWzFdYCBpbmRpdmlkdWFscyB3ZXJlIGV4YW1pbmVkLiBDcml0aWNhbCB0aGVybWFsIGxpbWl0cyBhbmQgYm9keSBzaXplIG1lYXN1cmVtZW50cyB3ZXJlIG1hZGUgYmVmb3JlIGluZGl2aWR1YWxzIHdlcmUgcHJlc2VydmVkIGluIGV0aGFub2wuIFdlIGV4Y2x1ZGVkIGRhdGEgZm9yIGByIGRpbShleGNsdWRlZClbMV1gIGluZGl2aWR1YWxzLCBkZXRhaWxlZCBiZWxvdy4gVGhlc2UgaW5kaXZpZHVhbHMgaGFkIGVpdGhlciB2ZXJ5IGxvdyBDVG1heCBvciB3ZXJlLCB1cG9uIHJlLWV4YW1pbmF0aW9uIG9mIHBob3RvZ3JhcGhzLCBpZGVudGlmaWVkIGFzIGp1dmVuaWxlcyBpbnN0ZWFkIG9mIG1hdHVyZSBmZW1hbGVzLiBXaXRoIHRoZXNlIGluZGl2aWR1YWxzIGV4Y2x1ZGVkLCAqKnRoZSBmdWxsIGRhdGEgc2V0IGNvbnRhaW5zIGByIGRpbShmdWxsX2RhdGEpWzFdYCBwaGVub3R5cGVkIGluZGl2aWR1YWxzKiouICAgCgpgYGB7ciBleGNsdWRlZC1pbmRzfQpleGNsdWRlZCAlPiUgCiAgc2VsZWN0KHJlZ2lvbiwgc2l0ZSwgc2Vhc29uLCBjb2xsZWN0aW9uX3RlbXAsIGNvbGxlY3Rpb25fc2FsaW5pdHksIHJlcGxpY2F0ZSwgdHViZSwgY3RtYXgsIHNpemUpICU+JSAKICBrbml0cjo6a2FibGUoYWxpZ24gPSAiYyIpCmBgYAoKQ3JpdGljYWwgdGhlcm1hbCBtYXhpbWEgKENUbWF4KSB3YXMgbWVhc3VyZWQgdXNpbmcgYSBjdXN0b20gc2V0dXAuIFRoZSBtZXRob2QgdXNlcyBhIHN0YW5kYXJkIGR5bmFtaWMgcmFtcGluZyBhc3NheSB0byBkZXRlcm1pbmUgdGhlIG1heGltdW0gdGVtcGVyYXR1cmUgaW5kaXZpZHVhbHMgY291bGQgc3VzdGFpbiBub3JtYWwgZnVuY3Rpb25pbmcuIFRoaXMgZGlmZmVycyBmcm9tIGxldGhhbCB0ZW1wZXJhdHVyZXMsIGFuZCBpbmRlZWQsIGFsbCBpbmRpdmlkdWFscyBvYnNlcnZlZCBzbyBmYXIgcmVjb3ZlcmVkIGZvbGxvd2luZyB0aGUgYXNzYXkuCgpJbmRpdmlkdWFscyB3ZXJlIHJlc3RlZCBmb3Igb25lIGhvdXIgYWZ0ZXIgY29sbGVjdGlvbiBiZWZvcmUgdGhlIGFzc2F5LiBEdXJpbmcgdGhlIGFzc2F5LCBjb3BlcG9kcyB3ZXJlIGhlbGQgaW4gYXJ0aWZpY2lhbCBzZWF3YXRlciwgY29tcG9zZWQgb2YgYm90dGxlZCBzcHJpbmcgd2F0ZXIgYW5kIEluc3RhbnQgT2NlYW4gc2FsdCBtaXggYWRqdXN0ZWQgdG8gbWF0Y2ggY29sbGVjdGlvbiBzYWxpbml0aWVzLiBEdXJpbmcgdGhlIGFzc2F5LCBzZXZlcmFsICdjb250cm9sJyBpbmRpdmlkdWFscyB3ZXJlIG1haW50YWluZWQgaW4gdGhpcyBzb2x1dGlvbiBhdCBhbWJpZW50IHRlbXBlcmF0dXJlcyB3aXRob3V0IHRoZSB0ZW1wZXJhdHVyZSByYW1wIHRvIGVuc3VyZSB0aGF0IHRoZXJlIHdhcyBubyBiYWNrZ3JvdW5kIG1vcnRhbGl0eS4gV2hlbiBzb3J0aW5nIGluZGl2aWR1YWxzIGZyb20gdGhlIHBsYW5rdG9uIHRvdyBjb250ZW50cywgdGhleSB3ZXJlIGhlbGQgaW4gYSA1MDo1MCBtaXggb2YgNjAgdW0gZmlsdGVyZWQgd2F0ZXIgZnJvbSB0aGUgY29sbGVjdGlvbiBzaXRlIGFuZCBhcnRpZmljaWFsIHNlYXdhdGVyIGFzIGFuIGFkZGl0aW9uYWwgYWNjbGltYXRpb24gc3RlcC4gCgpTaG93biBiZWxvdyBhcmUgdGhlIG1lYXN1cmVkIENUbWF4IHZhbHVlcy4gTm90ZTogQ1RtYXggdmFsdWVzIGZvciB0aGUgZWFybHkgc2Vhc29uIEtleSBMYXJnbyBjb3BlcG9kcyB3ZXJlIGNvbGxlY3RlZCBhdCB0aGUgZW5kIG9mIEZlYnJ1YXJ5IDIwMjMgYXMgcGFydCBvZiBhIHNlcGFyYXRlIHByb2plY3QuIEJvZHkgc2l6ZSB2YWx1ZXMgd2VyZSBub3QgbWVhc3VyZWQgZHVyaW5nIHRoaXMgcHJvamVjdCwgbm9yIHdlcmUgY29wZXBvZHMgaW5kaXZpZHVhbGx5IHByZXNlcnZlZCBhZnRlciB0aGUgZXhwZXJpbWVudHMuIFRoZXNlIGVhcmx5IHNlYXNvbiBDVG1heCB2YWx1ZXMgYXJlIGluY2x1ZGVkIGFzIGEgcG9pbnQgb2YgY29tcGFyaXNvbi4gSW5kaXZpZHVhbCBtZWFzdXJlbWVudHMgYXJlIHNob3duIGluIHNtYWxsIHBvaW50cyBmb3IgZWFjaCBjb2xsZWN0aW9uLiBUaGUgbGFyZ2UgcG9pbnRzIGluZGljYXRlIHRoZSBtZWRpYW4gdmFsdWVzIGZvciBlYWNoIGNvbGxlY3Rpb24uIAoKYGBge3Igc2Vhc29uYWwtY3QtbWF4fQptZWFuX2N0bWF4ID0gZnVsbF9kYXRhICU+JSAKICBncm91cF9ieShzaXRlLCBzZWFzb24sIGRveSwgY29sbGVjdGlvbl90ZW1wKSAlPiUgCiAgc3VtbWFyaXplKG1lYW5fY3RtYXggPSBtZWFuKGN0bWF4KSwKICAgICAgICAgICAgbWVkaWFuX2N0bWF4ID0gbWVkaWFuKGN0bWF4KSkKCmdncGxvdChmdWxsX2RhdGEsIGFlcyh4ID0gc2Vhc29uLCB5ID0gY3RtYXgsIGNvbG91ciA9IHNpdGUpKSArIAogIGdlb21fbGluZShkYXRhID0gbWVhbl9jdG1heCwgCiAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX2N0bWF4LCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4xLCBqaXR0ZXIuaGVpZ2h0ID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9kZ2Uud2lkdGggPSAwLjQpLAogICAgICAgICAgICAgYWxwaGEgPSAwLjMpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gbWVhbl9jdG1heCwgCiAgICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCksCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgIHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCAowrBDKSIsCiAgICAgICB4ID0gIlNlYXNvbiIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICBsZWdlbmQudGl0bGUuYWxpZ24gPSAwLjEyNSkKYGBgCgpUaGUgc2FtZSBkYXRhIGlzIHNob3duIGJlbG93LCBwbG90dGVkIGFnYWluc3QgZGF5IG9mIHRoZSB5ZWFyIGluc3RlYWQgb2Ygc2Vhc29uLiBUaGlzIGFjY291bnRzIGZvciB0aGUgdmFyaWFibGUgdGltaW5nIG9mIGNvbGxlY3Rpb25zIGFjcm9zcyByZWdpb25zIChlLmcuIC0gdGhlIGNvbXByZXNzZWQgY29sbGVjdGlvbnMgZnJvbSB0aGUgTm9ydGhlcm4gc2l0ZXMgdG8gYWNjb21vZGF0ZSB0aGUgZWFybGllciBvbnNldCBvZiBjb2xkIHRlbXBlcmF0dXJlcykuIAoKYGBge3IgZG95LWN0LW1heH0KZ2dwbG90KGZpbHRlcihmdWxsX2RhdGEsIHNpdGUgIT0gIktleSBMYXJnbyIpLCBhZXMoeCA9IGRveSwgeSA9IGN0bWF4LCBjb2xvdXIgPSBzaXRlKSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IGZpbHRlcihtZWFuX2N0bWF4LCBzaXRlICE9ICJLZXkgTGFyZ28iKSwgCiAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX2N0bWF4LCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4xLCBqaXR0ZXIuaGVpZ2h0ID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9kZ2Uud2lkdGggPSAwLjQpLAogICAgICAgICAgICAgYWxwaGEgPSAwLjMpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gZmlsdGVyKG1lYW5fY3RtYXgsIHNpdGUgIT0gIktleSBMYXJnbyIpLCAKICAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX2N0bWF4KSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICAgICAgICAgICAgc2l6ZSA9IDQpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIkNUbWF4ICjCsEMpIiwKICAgICAgIHggPSAiU2Vhc29uIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIAogICAgICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IDAuMTI1KQpgYGAKCkNUbWF4IGRhdGEgZm9yIGVhY2ggaW5kaXZpZHVhbCBzaXRlIGlzIHNob3duIGJlbG93LCBwbG90dGVkIGFnYWluc3QgZGF5IG9mIHRoZSB5ZWFyLiBUaGUgZ3JleSBsaW5lIGluIGVhY2ggZmFjZXQgc2hvd3MgdGhlIGNvbGxlY3Rpb24gdGVtcGVyYXR1cmVzLiBOb3RlIHRoYXQgYm90aCBheGVzIHZhcnkgYWNyb3NzIGZhY2V0cy4gIAoKYGBge3IgY3RtYXgtaW5kLXBvcHMtZG95LCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02fQpnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IGRveSwgeSA9IGN0bWF4LCBjb2xvdXIgPSBzaXRlKSkgKyAKICBmYWNldF93cmFwKC5+c2l0ZSwgc2NhbGVzID0gImZyZWUiKSArIAogIGdlb21fbGluZShkYXRhID0gbWVhbl9jdG1heCwgCiAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX2N0bWF4LCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMywgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9saW5lKGRhdGEgPSBtZWFuX2N0bWF4LCAKICAgICAgICAgICAgYWVzKHkgPSBjb2xsZWN0aW9uX3RlbXAsIGdyb3VwID0gc2l0ZSksCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICAgICAgICAgICBsaW5ld2lkdGggPSAyLAogICAgICAgICAgICBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgaml0dGVyLmhlaWdodCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvZGdlLndpZHRoID0gMC40KSwKICAgICAgICAgICAgIGFscGhhID0gMC44KSArIAogICMgZ2VvbV9wb2ludChkYXRhID0gbWVhbl9jdG1heCwgCiAgIyAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX2N0bWF4KSwKICAjICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgIyAgICAgICAgICAgIHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCAowrBDKSIsCiAgICAgICB4ID0gIkRheSBvZiBZZWFyIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgCiAgICAgICAgbGVnZW5kLnRpdGxlLmFsaWduID0gMC4xMjUpCmBgYAoKYGBge3IgY3RtYXgtaW5kLXBvcHMtc2Vhc29uLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02LCBpbmNsdWRlID0gRn0KZ2dwbG90KGZ1bGxfZGF0YSwgYWVzKHggPSBzZWFzb24sIHkgPSBjdG1heCwgY29sb3VyID0gc2l0ZSkpICsgCiAgZmFjZXRfd3JhcCgufnNpdGUsIHNjYWxlcyA9ICJmcmVlX3kiKSArIAogIGdlb21fbGluZShkYXRhID0gbWVhbl9jdG1heCwgCiAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX2N0bWF4LCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMywgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9saW5lKGRhdGEgPSBtZWFuX2N0bWF4LCAKICAgICAgICAgICAgYWVzKHkgPSBjb2xsZWN0aW9uX3RlbXAsIGdyb3VwID0gc2l0ZSksCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICAgICAgICAgICBsaW5ld2lkdGggPSAyLAogICAgICAgICAgICBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgaml0dGVyLmhlaWdodCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvZGdlLndpZHRoID0gMC40KSwKICAgICAgICAgICAgIGFscGhhID0gMC44KSArIAogICMgZ2VvbV9wb2ludChkYXRhID0gbWVhbl9jdG1heCwgCiAgIyAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX2N0bWF4KSwKICAjICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgIyAgICAgICAgICAgIHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCAowrBDKSIsCiAgICAgICB4ID0gIlNlYXNvbiIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IDAuMTI1KQpgYGAKCgojIyMgV2FybWluZyB0b2xlcmFuY2UKCldhcm1pbmcgdG9sZXJhbmNlICh0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZXJtYWwgbGltaXRzIGFuZCBlbnZpcm9ubWVudGFsIHRlbXBlcmF0dXJlcykgaXMgYSBjb21tb25seSB1c2VkIG1ldHJpYyBvZiBjbGltYXRlIHZ1bG5lcmFiaWxpdHkuIFdlIGNhbGN1bGF0ZWQgdGhpcyBhcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIG1lYXN1cmVkIENUbWF4IHZhbHVlcyBhbmQgdGhlIGNvbGxlY3Rpb24gdGVtcGVyYXR1cmUuIFNtYWxsZXIgd2FybWluZyB0b2xlcmFuY2UgdmFsdWVzIGluZGljYXRlIHRoYXQgcG9wdWxhdGlvbnMgd2VyZSBuZWFyZXIgdG8gdGhlaXIgdXBwZXIgdGhlcm1hbCBsaW1pdHMsIGFuZCBtYXkgdGhlcmVmb3JlIGJlIG1vcmUgdnVsbmVyYWJsZSB0byBhZGRpdGlvbmFsIHdhcm1pbmcuIAoKYGBge3Igc2Vhc29uYWwtd2FybWluZy10b2x9Cm1lYW5fd3QgPSBmdWxsX2RhdGEgJT4lIAogIGdyb3VwX2J5KHNpdGUsIHNlYXNvbikgJT4lIAogIHN1bW1hcml6ZShtZWFuX3d0ID0gbWVhbih3YXJtaW5nX3RvbCksCiAgICAgICAgICAgIG1lZGlhbl93dCA9IG1lZGlhbih3YXJtaW5nX3RvbCkpCgpnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IHNlYXNvbiwgeSA9IHdhcm1pbmdfdG9sLCBjb2xvdXIgPSBzaXRlKSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IG1lYW5fd3QsIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl93dCwgZ3JvdXAgPSBzaXRlKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgaml0dGVyLmhlaWdodCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvZGdlLndpZHRoID0gMC40KSwKICAgICAgICAgICAgIGFscGhhID0gMC4zKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IG1lYW5fd3QsIAogICAgICAgICAgICAgYWVzKHkgPSBtZWRpYW5fd3QpLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiV2FybWluZyBUb2xlcmFuY2UgKMKwQykiLAogICAgICAgeCA9ICJTZWFzb24iKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwgCiAgICAgICAgbGVnZW5kLnRpdGxlLmFsaWduID0gMC4xMjUpCmBgYAoKIyMjIEJvZHkgU2l6ZQoKRm9sbG93aW5nIHRoZSBDVG1heCBhc3NheSwgaW5kaXZpZHVhbHMgd2VyZSBwaG90b2dyYXBoZWQgZm9yIGJvZHkgc2l6ZSBtZWFzdXJlbWVudHMuIFByb3NvbWUgbGVuZ3RocyB3ZXJlIG1lYXN1cmVkIGZyb20gdGhlc2UgcGhvdG9ncmFwaHMgdXNpbmcgYSBzY2FsZSBtaWNyb21ldGVyIGFuZCB0aGUgc29mdHdhcmUgSW1hZ2VKLiBUaGVzZSBtZWFzdXJlbWVudHMgYXJlIHNob3duIGJlbG93LiBBcyBiZWZvcmUsIGxhcmdlIHBvaW50cyBpbmRpY2F0ZSB0aGUgbWVkaWFuIGJvZHkgc2l6ZS4gCgpgYGB7ciBzZWFzb25hbC1ib2R5LXNpemV9Cm1lYW5fc2l6ZSA9IGZ1bGxfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoc2l0ZSwgc2Vhc29uLCBkb3ksIGNvbGxlY3Rpb25fdGVtcCkgJT4lIAogIHN1bW1hcml6ZShtZWFuX3NpemUgPSBtZWFuKHNpemUpLAogICAgICAgICAgICBtZWRpYW5fc2l6ZSA9IG1lZGlhbihzaXplKSkKCmdncGxvdChmdWxsX2RhdGEsIGFlcyh4ID0gc2Vhc29uLCB5ID0gc2l6ZSwgY29sb3VyID0gc2l0ZSkpICsgCiAgZ2VvbV9saW5lKGRhdGEgPSBtZWFuX3NpemUsIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9zaXplLCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4xLCBqaXR0ZXIuaGVpZ2h0ID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9kZ2Uud2lkdGggPSAwLjQpLAogICAgICAgICAgICAgYWxwaGEgPSAwLjMpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gbWVhbl9zaXplLCAKICAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX3NpemUpLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiUHJvc29tZSBMZW5ndGggKG1tKSIsCiAgICAgICB4ID0gIlNlYXNvbiIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICBsZWdlbmQudGl0bGUuYWxpZ24gPSAwLjEyNSkKYGBgCgpgYGB7ciBkb3ktYm9keS1zaXplfQpnZ3Bsb3QoZHJvcF9uYShmdWxsX2RhdGEsIHNpemUpLCBhZXMoeCA9IGRveSwgeSA9IHNpemUsIGNvbG91ciA9IHNpdGUpKSArIAogIGdlb21fbGluZShkYXRhID0gZHJvcF9uYShtZWFuX3NpemUsIG1lYW5fc2l6ZSksIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9zaXplLCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4xLCBqaXR0ZXIuaGVpZ2h0ID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9kZ2Uud2lkdGggPSAwLjQpLAogICAgICAgICAgICAgYWxwaGEgPSAwLjMpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gZHJvcF9uYShtZWFuX3NpemUsIG1lYW5fc2l6ZSksIAogICAgICAgICAgICAgYWVzKHkgPSBtZWRpYW5fc2l6ZSksCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgIHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJQcm9zb21lIExlbmd0aCAobW0pIiwKICAgICAgIHggPSAiU2Vhc29uIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIAogICAgICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IDAuMTI1KQpgYGAKCmBgYHtyIHNpemUtaW5kLXBvcHMtZG95LCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02fQpnZ3Bsb3QoZHJvcF9uYShmdWxsX2RhdGEsIHNpemUpLCBhZXMoeCA9IGRveSwgeSA9IHNpemUsIGNvbG91ciA9IHNpdGUpKSArIAogIGZhY2V0X3dyYXAoLn5zaXRlKSArIAogIGdlb21fbGluZShkYXRhID0gZHJvcF9uYShtZWFuX3NpemUsIG1lYW5fc2l6ZSksIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9zaXplLCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMywgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgaml0dGVyLmhlaWdodCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvZGdlLndpZHRoID0gMC40KSwKICAgICAgICAgICAgIGFscGhhID0gMC44KSArIAogICMgZ2VvbV9wb2ludChkYXRhID0gbWVhbl9jdG1heCwgCiAgIyAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX2N0bWF4KSwKICAjICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgIyAgICAgICAgICAgIHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJQcm9zb21lIExlbmd0aCAobW0pIiwKICAgICAgIHggPSAiRGF5IG9mIFllYXIiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAgICAgICBsZWdlbmQudGl0bGUuYWxpZ24gPSAwLjEyNSkKYGBgCgoKYGBge3Igc2l6ZS1pbmQtcG9wcy1zZWFzb24sIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTYsIGluY2x1ZGUgPSBGfQpnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IHNlYXNvbiwgeSA9IHNpemUsIGNvbG91ciA9IHNpdGUpKSArIAogIGZhY2V0X3dyYXAoLn5zaXRlKSArIAogIGdlb21fbGluZShkYXRhID0gbWVhbl9zaXplLCAKICAgICAgICAgICAgYWVzKHkgPSBtZWRpYW5fc2l6ZSwgZ3JvdXAgPSBzaXRlKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDMsIGFscGhhID0gMC41KSArIAogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAwLjEsIGppdHRlci5oZWlnaHQgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb2RnZS53aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBhbHBoYSA9IDAuOCkgKyAKICAjIGdlb21fcG9pbnQoZGF0YSA9IG1lYW5fY3RtYXgsIAogICMgICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCksCiAgIyAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICMgICAgICAgICAgICBzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiUHJvc29tZSBMZW5ndGggKG1tKSIsCiAgICAgICB4ID0gIlNlYXNvbiIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IDAuMTI1KQpgYGAKCiMjIyBTYWxpbml0eSBQYWlyIENvbXBhcmlzb25zIAoKVGhlIHRocmVlIHBhaXJzIG9mIHNhbGluaXR5IGNvbXBhcmlzb25zIGRvIG5vdCBzaG93IGFueSBnZW5lcmFsIHBhdHRlcm4sIHdpdGggdmFyaWF0aW9uIGRvbWluYXRlZCBieSBzZWFzb25hbCBjaGFuZ2VzLiAKCmBgYHtyIHNhbC1wYWlyLXRyYWl0c30Kc2FsX2NvbXBfY3RtYXhfcGxvdCA9IHNhbF9jb21wcyAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc2FsaW5pdHksIHkgPSBjdG1heCwgY29sb3VyID0gc2Vhc29uLCBncm91cCA9IHNlYXNvbikpICsgCiAgZmFjZXRfd3JhcChyZWdpb25+LikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMikpICsgCiAgI2dlb21fbGluZShzaXplID0gMS41KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2Vhc29uX2NvbHMpICsgCiAgbGFicyh5ID0gIkNUbWF4ICjCsEMpIiwKICAgICAgIHggPSAiIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cyhiYXNlX3NpemUgPSAxNCkKCnNhbF9jb21wX3NpemVfcGxvdCA9IHNhbF9jb21wcyAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc2FsaW5pdHksIHkgPSBzaXplLCBjb2xvdXIgPSBzZWFzb24sIGdyb3VwID0gc2Vhc29uKSkgKyAKICBmYWNldF93cmFwKHJlZ2lvbn4uKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDIsIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMikpICsgCiAgI2dlb21fbGluZShzaXplID0gMS41KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2Vhc29uX2NvbHMpICsgCiAgbGFicyh5ID0gIlByb3NvbWUgTGVuZ3RoIChtbSkiLAogICAgICAgeCA9ICIiKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKGJhc2Vfc2l6ZSA9IDE0KQoKZ2dhcnJhbmdlKHNhbF9jb21wX2N0bWF4X3Bsb3QsIHNhbF9jb21wX3NpemVfcGxvdCwgbnJvdyA9IDIsIGNvbW1vbi5sZWdlbmQgPSBULCBsZWdlbmQgPSAicmlnaHQiKQoKIyMjCgpzYWxfY29tcF9jdG1heC5tb2RlbCA9IGxtKGN0bWF4IH4gY29sbGVjdGlvbl90ZW1wLCBkYXRhID0gc2FsX2NvbXBzKQojIHN1bW1hcnkoY3RtYXhfdGVtcC5tb2RlbCkKIyBjYXI6OkFub3ZhKGN0bWF4X3RlbXAubW9kZWwpCnNhbF9jb21wX2N0bWF4X3Jlc2lkcyA9IHJlc2lkdWFscyhzYWxfY29tcF9jdG1heC5tb2RlbCkKCnNhbF9jb21wX3NpemUubW9kZWwgPSBsbShzaXplIH4gY29sbGVjdGlvbl90ZW1wLCBkYXRhID0gc2FsX2NvbXBzKQojIHN1bW1hcnkoc2l6ZV90ZW1wLm1vZGVsKQojIGNhcjo6QW5vdmEoc2l6ZV90ZW1wLm1vZGVsKQpzYWxfY29tcF9zaXplX3Jlc2lkcyA9IHJlc2lkdWFscyhzYWxfY29tcF9zaXplLm1vZGVsKQoKc2FsX2NvbXBfY3RtYXhfcmVzaWRfcGxvdCA9IHNhbF9jb21wcyAlPiUKICBtdXRhdGUoY3RtYXhfcmVzaWRzID0gc2FsX2NvbXBfY3RtYXhfcmVzaWRzLAogICAgICAgICBzaXplX3Jlc2lkcyA9IHNhbF9jb21wX3NpemVfcmVzaWRzKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzYWxpbml0eSwgeSA9IGN0bWF4X3Jlc2lkcywgY29sb3VyID0gc2Vhc29uLCBncm91cCA9IHNlYXNvbikpICsKICBmYWNldF93cmFwKHJlZ2lvbn4uKSArCiAgZ2VvbV9wb2ludChzaXplID0gMiwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpKSArCiAgI2dlb21fbGluZShzaXplID0gMS41KSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzZWFzb25fY29scykgKwogIGxhYnMoeSA9ICJDVG1heCBcblJlc2lkdWFscyIsCiAgICAgICB4ID0gIiIpICsKICB0aGVtZV9tYXR0X2ZhY2V0cyhiYXNlX3NpemUgPSAxNCkKCnNhbF9jb21wX3NpemVfcmVzaWRfcGxvdCA9IHNhbF9jb21wcyAlPiUKICBtdXRhdGUoY3RtYXhfcmVzaWRzID0gc2FsX2NvbXBfY3RtYXhfcmVzaWRzLAogICAgICAgICBzaXplX3Jlc2lkcyA9IHNhbF9jb21wX3NpemVfcmVzaWRzKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzYWxpbml0eSwgeSA9IHNpemVfcmVzaWRzLCBjb2xvdXIgPSBzZWFzb24sIGdyb3VwID0gc2Vhc29uKSkgKwogIGZhY2V0X3dyYXAocmVnaW9ufi4pICsKICBnZW9tX3BvaW50KHNpemUgPSAyLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNSkpICsKICAjZ2VvbV9saW5lKHNpemUgPSAxLjUpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNlYXNvbl9jb2xzKSArCiAgbGFicyh5ID0gIlByb3NvbWUgTGVuZ3RoIFxuUmVzaWR1YWxzIiwKICAgICAgIHggPSAiIikgKwogIHRoZW1lX21hdHRfZmFjZXRzKGJhc2Vfc2l6ZSA9IDE0KQoKI2dnYXJyYW5nZShzYWxfY29tcF9jdG1heF9yZXNpZF9wbG90LCBzYWxfY29tcF9zaXplX3Jlc2lkX3Bsb3QsIG5yb3cgPSAyLCBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gInJpZ2h0IikKYGBgCgoKIyMgVHJhaXQgQ29ycmVsYXRpb25zCgpXZSBleHBlY3QgdGhhdCBjb2xsZWN0aW9ucyBmcm9tIHdhcm1lciB3YXRlcnMgc2hvdWxkIHlpZWxkIGNvcGVwb2RzIHdpdGggaGlnaGVyIHRoZXJtYWwgbGltaXRzIGFuZCBzbWFsbGVyIGJvZHkgc2l6ZXMuIE91ciBvYnNlcnZhdGlvbnMgbGFyZ2VseSBmaXQgdGhpcyBleHBlY3RhdGlvbiwgd2l0aCBzdHJvbmcgaW5jcmVhc2VzIGluIENUbWF4IGF0IGhpZ2hlciB0ZW1wZXJhdHVyZXMsIGFuZCBhIGdlbmVyYWwgZGVjcmVhc2UgaW4gcHJvc29tZSBsZW5ndGhzIGFzIHRlbXBlcmF0dXJlIGluY3JlYXNlZC4gCgpgYGB7ciB0ZW1wLWNvcnMsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD02fQpjdG1heF90ZW1wX3Bsb3QgPSBnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IGN0bWF4KSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMiwgCiAgICAgICAgICAgICAgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNpdGUpLCAKICAgICAgICAgICAgIHNpemUgPSAyLCBhbHBoYSA9IDAuNykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCnNpemVfdGVtcF9wbG90ID0gZ2dwbG90KGZ1bGxfZGF0YSwgYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBzaXplKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMiwgCiAgICAgICAgICAgICAgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNpdGUpLCAKICAgICAgICAgICAgIHNpemUgPSAyLCBhbHBoYSA9IDAuNykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiUHJvc29tZSBMZW5ndGggKG1tKSIsCiAgICAgICB4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCnd0X3RlbXBfcGxvdCA9IGdncGxvdChmdWxsX2RhdGEsIGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gd2FybWluZ190b2wpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVCwKICAgICAgICAgICAgICBsaW5ld2lkdGggPSAyLCAKICAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gc2l0ZSksIAogICAgICAgICAgICAgc2l6ZSA9IDIsIGFscGhhID0gMC43KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJXYXJtaW5nIFRvbGVyYW5jZSAowrBDKSIsCiAgICAgICB4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmdnYXJyYW5nZShjdG1heF90ZW1wX3Bsb3QsIHd0X3RlbXBfcGxvdCwgc2l6ZV90ZW1wX3Bsb3QsIGNvbW1vbi5sZWdlbmQgPSBULCBsZWdlbmQgPSAiYm90dG9tIiwgbnJvdyA9IDEpCmBgYAoKYGBge3IgaW5jbHVkZSA9IEZ9CmdncGxvdChmdWxsX2RhdGEsIGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gY3RtYXgpKSArIAogIGZhY2V0X3dyYXAoLn5zaXRlKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVCwKICAgICAgICAgICAgICBsaW5ld2lkdGggPSAyLCAKICAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gc2l0ZSksIAogICAgICAgICAgICAgc2l6ZSA9IDIsIGFscGhhID0gMC43KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCAowrBDKSIsCiAgICAgICB4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKZ2dwbG90KGZ1bGxfZGF0YSwgYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBzaXplKSkgKyAKICBmYWNldF93cmFwKC5+c2l0ZSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMiwgCiAgICAgICAgICAgICAgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNpdGUpLCAKICAgICAgICAgICAgIHNpemUgPSAyLCBhbHBoYSA9IDAuNykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiUHJvc29tZSBMZW5ndGggKG1tKSIsCiAgICAgICB4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKYGBgCgpPZiBwYXJ0aWN1bGFyIGludGVyZXN0IGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBwcm9zb21lIGxlbmd0aCBhbmQgQ1RtYXguIEluIG1hbnkgY2FzZXMsIGxhcmdlciBib2R5IHNpemVzIGFyZSBhc3NvY2lhdGVkIHdpdGggY29sZCBhZGFwdGF0aW9uL2FjY2xpbWF0aW9uLiBXZSBtYXkgdGhlcmVmb3JlIHNlZSB0aGlzIHBhdHRlcm4gZW1lcmdlIGFjcm9zcyBwb3B1bGF0aW9ucyBvciBzZWFzb25zLiBJZiBwb3B1bGF0aW9ucyBjb250YWluIGEgbWl4IG9mIGNvbGQtIGFuZCB3YXJtLWFkYXB0ZWQgZ2Vub3R5cGVzLCBob3dldmVyLCB3ZSBtaWdodCBhbHNvIHNlZSB0aGlzIHJlbGF0aW9uc2hpcCBlbWVyZ2UgKip3aXRoaW4qKiBwb3B1bGF0aW9ucyBvciBldmVuIGluZGl2aWR1YWwgY29sbGVjdGlvbnMuIFNob3duIGJlbG93IGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBwcm9zb21lIGxlbmd0aCBhbmQgQ1RtYXggaW4gb3VyIGRhdGEgc2V0LiBJbmRpdmlkdWFsIHJlZ3Jlc3Npb24gbGluZXMgZm9yIGVhY2ggc2l0ZSBhcmUgYWxzbyBpbmNsdWRlZCAtIHRoZSBkYXJrIGdyZXkgbGluZXMgaW4gdGhlIGJhY2tncm91bmQgcmVwcmVzZW50IHRoZSAndW5pdmVyc2FsJyByZWdyZXNzaW9uIGZvciB0aGF0IHNpdGUsIHdpdGggaW5kaXZpZHVhbCBjb2xvcmVkIHJlZ3Jlc3Npb24gbGluZXMgZm9yIGVhY2ggY29sbGVjdGlvbi4gICAgCgpgYGB7ciBjdG1heC12cy1zaXplLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD0xMH0KdW5pdmVyc2FsX3NpemUgPSBmdWxsX2RhdGEgJT4lIAogIGdncGxvdChhZXMoeCA9IHNpemUsIHkgPSBjdG1heCkpICsgCiAgIyBnZW9tX3Ntb290aChkYXRhID0gZmlsdGVyKGZ1bGxfZGF0YSwgY3RtYXggPiAzMSksIAogICMgICAgICAgICAgICAgYWVzKHggPSBzaXplLCB5ID0gY3RtYXgpLAogICMgICAgICAgICAgICAgbWV0aG9kID0gImxtIiwgCiAgIyAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTYwIiwgCiAgIyAgICAgICAgICAgICBzZSA9IEYsCiAgIyAgICAgICAgICAgICBsaW5ld2lkdGggPSAyKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVCwKICAgICAgICAgICAgICBsaW5ld2lkdGggPSAyLAogICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5NzAiKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNpdGUpLAogICAgICAgICAgICAgc2l6ZSA9IDIsIGFscGhhID0gMC43KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCAowrBDKSIsCiAgICAgICB4ID0gIiIpICsKICB0aGVtZV9tYXR0KGJhc2Vfc2l6ZSA9IDE0KSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKQoKcG9wX3NpemUgPSBmdWxsX2RhdGEgJT4lIAogIGdncGxvdChhZXMoeCA9IHNpemUsIHkgPSBjdG1heCwgY29sb3VyID0gc2l0ZSwgZ3JvdXAgPSBzZWFzb24pKSArIAogIGZhY2V0X3dyYXAoc2l0ZX4uKSArIAogICMgZ2VvbV9zbW9vdGgoZGF0YSA9IGZpbHRlcihmdWxsX2RhdGEsIGN0bWF4ID4gMzEpLCAKICAjICAgICAgICAgICAgIGFlcyh4ID0gc2l6ZSwgeSA9IGN0bWF4KSwKICAjICAgICAgICAgICAgIG1ldGhvZCA9ICJsbSIsIAogICMgICAgICAgICAgICAgY29sb3VyID0gImdyZXk2MCIsIAogICMgICAgICAgICAgICAgc2UgPSBGLAogICMgICAgICAgICAgICAgbGluZXdpZHRoID0gMikgKyAKICBnZW9tX3Ntb290aChkYXRhID0gZnVsbF9kYXRhLCAKICAgICAgICAgICAgICBhZXMoeCA9IHNpemUsIHkgPSBjdG1heCwgZ3JvdXAgPSBzaXRlKSwgCiAgICAgICAgICAgICAgY29sb3VyID0gImdyZXkyMCIsIG1ldGhvZCA9ICJsbSIsIHNlID0gRikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAxLjMsIGFscGhhID0gMC4zKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwKICAgICAgICAgICAgICBsaW5ld2lkdGggPSAxKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDAuNiwgMC44LCAxKSkgKyAKICBsYWJzKHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgeCA9ICJQcm9zb21lIExlbmd0aCAobW0pIikgKwogIHRoZW1lX21hdHQoYmFzZV9zaXplID0gMTQpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmdnYXJyYW5nZSh1bml2ZXJzYWxfc2l6ZSwgcG9wX3NpemUsIGNvbW1vbi5sZWdlbmQgPSBULCBsZWdlbmQgPSAibm9uZSIsIG5yb3cgPSAyKQpgYGAKClRoaXMgcmVsYXRpb25zaGlwIG1heSBiZSBhZmZlY3RlZCBieSBjaGFuZ2VzIGluIHRlbXBlcmF0dXJlIGF0IGVhY2ggc2l0ZSwgaG93ZXZlciwgd2hpY2ggaXMgY29udHJvbGxlZCBmb3IgaGVyZSBieSBleGFtaW5pbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIENUbWF4IGFuZCBzaXplIHJlc2lkdWFscywgYWNxdWlyZWQgZnJvbSByZWdyZXNzaW9ucyBvZiB0aGVzZSB0cmFpdHMgYWdhaW5zdCBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlLiBUaGlzIHN1YnN0YW50aWFsbHkgcmVkdWNlcyB0aGUgc3RyZW5ndGggb2YgdGhlIGFwcGFyZW50IHJlbGF0aW9uc2hpcCwgYnV0IHRoZXJlIGlzIHN0aWxsIGEgc2xpZ2h0bHkgbmVnYXRpdmUgb3ZlcmFsbCByZWxhdGlvbnNoaXAuICAgICAKCmBgYHtyIGN0bWF4LXZzLXNpemUtcmVzaWRzLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD0xMH0KZmlsdGVyZWRfZGF0YSA9IGZ1bGxfZGF0YSAlPiUgCiAgZHJvcF9uYShzaXplLCBjdG1heCkKCmN0bWF4X3RlbXAubW9kZWwgPSBsbShjdG1heCB+IGNvbGxlY3Rpb25fdGVtcCArIHNpdGUsIGRhdGEgPSBmaWx0ZXJlZF9kYXRhKQpjdG1heF9yZXNpZHMgPSByZXNpZHVhbHMoY3RtYXhfdGVtcC5tb2RlbCkKCnNpemVfdGVtcC5tb2RlbCA9IGxtKHNpemUgfiBjb2xsZWN0aW9uX3RlbXAgKyBzaXRlLCBkYXRhID0gZmlsdGVyZWRfZGF0YSkKc2l6ZV9yZXNpZHMgPSByZXNpZHVhbHMoc2l6ZV90ZW1wLm1vZGVsKQoKdW5pdmVyc2FsX3Jlc2lkcyA9IGZpbHRlcmVkX2RhdGEgJT4lIAogIG11dGF0ZShjdG1heF9yZXNpZHMgPSBjdG1heF9yZXNpZHMsCiAgICAgICAgIHNpemVfcmVzaWRzID0gc2l6ZV9yZXNpZHMpIAoKYWxsX3Jlc2lkcyA9IGdncGxvdCh1bml2ZXJzYWxfcmVzaWRzLCBhZXMoeCA9IHNpemVfcmVzaWRzLCB5ID0gY3RtYXhfcmVzaWRzKSkgKyAKICAjIGdlb21fc21vb3RoKGRhdGEgPSBmaWx0ZXIoZnVsbF9kYXRhLCBjdG1heCA+IDMxKSwgCiAgIyAgICAgICAgICAgICBhZXMoeCA9IHNpemUsIHkgPSBjdG1heCksCiAgIyAgICAgICAgICAgICBtZXRob2QgPSAibG0iLCAKICAjICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5NjAiLCAKICAjICAgICAgICAgICAgIHNlID0gRiwKICAjICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDIpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULAogICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDIsCiAgICAgICAgICAgICAgY29sb3VyID0gImdyZXk3MCIpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gc2l0ZSksCiAgICAgICAgICAgICBzaXplID0gMiwgYWxwaGEgPSAwLjcpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIkNUbWF4IFJlc2lkdWFscyIsCiAgICAgICB4ID0gIiIpICsKICB0aGVtZV9tYXR0KGJhc2Vfc2l6ZSA9IDE0KSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKQoKcG9wX3Jlc2lkcyA9IGdncGxvdCh1bml2ZXJzYWxfcmVzaWRzLCBhZXMoeCA9IHNpemVfcmVzaWRzLCB5ID0gY3RtYXhfcmVzaWRzLCBjb2xvdXIgPSBzaXRlLCBncm91cCA9IHNlYXNvbikpICsgCiAgZmFjZXRfd3JhcChzaXRlfi4pICsgCiAgIyBnZW9tX3Ntb290aChkYXRhID0gZmlsdGVyKGZ1bGxfZGF0YSwgY3RtYXggPiAzMSksIAogICMgICAgICAgICAgICAgYWVzKHggPSBzaXplLCB5ID0gY3RtYXgpLAogICMgICAgICAgICAgICAgbWV0aG9kID0gImxtIiwgCiAgIyAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTYwIiwgCiAgIyAgICAgICAgICAgICBzZSA9IEYsCiAgIyAgICAgICAgICAgICBsaW5ld2lkdGggPSAyKSArIAogIGdlb21fc21vb3RoKGFlcyh4ID0gc2l6ZV9yZXNpZHMsIHkgPSBjdG1heF9yZXNpZHMsIGdyb3VwID0gc2l0ZSksIAogICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5MjAiLCBtZXRob2QgPSAibG0iLCBzZSA9IEYpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMS4zLCBhbHBoYSA9IDAuMykgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggUmVzaWR1YWxzIiwKICAgICAgIHggPSAiUHJvc29tZSBMZW5ndGggUmVzaWR1YWxzIikgKwogIHRoZW1lX21hdHQoYmFzZV9zaXplID0gMTQpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmdnYXJyYW5nZShhbGxfcmVzaWRzLCBwb3BfcmVzaWRzLCBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gIm5vbmUiLCBucm93ID0gMikKYGBgCgpgYGB7ciBjdG1heC1tb2RlbCwgaW5jbHVkZSA9IEZ9CiMgCiMgZnVsbC5tb2RlbCA9IGxtKGRhdGEgPSBmaWx0ZXJlZF9kYXRhLCAKIyAgICAgICAgICAgICAgICAgY3RtYXggfiBzaXRlICogY29sbGVjdGlvbl90ZW1wICogc2l6ZSwgCiMgICAgICAgICAgICAgICAgICAgIG5hLmFjdGlvbiA9ICJuYS5mYWlsIikKIyAKIyBkcmVkZ2VfcmVzdWx0cyA9IE11TUluOjpkcmVkZ2UoZnVsbC5tb2RlbCkKIyB0b3BfbW9kZWwgPSBNdU1Jbjo6Z2V0Lm1vZGVscyhkcmVkZ2VfcmVzdWx0cywgMSlbWzFdXSAjQmVzdCBtb2RlbAojIAojIHRlbXBfdmFscyA9IGFzX3RpYmJsZShlbXRyZW5kcyh0b3BfbW9kZWwsIHNwZWMgPSAic2l0ZSIsIHZhciA9ICJjb2xsZWN0aW9uX3RlbXAiKSkgCiMgc2l6ZV92YWxzID0gYXNfdGliYmxlKGVtdHJlbmRzKHRvcF9tb2RlbCwgc3BlYyA9ICJzaXRlIiwgdmFyID0gInNpemUiKSkgCgpgYGAKClRvIG1vcmUgZm9ybWFsbHkgdGVzdCB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIENUbWF4LCBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlLCBhbmQgc2l6ZSwgd2UgdXNlZCBhIGxpbmVhciBtaXhlZCBlZmZlY3RzIG1vZGVsLCBzdHJ1Y3R1cmVkIGFzIGBjdG1heCB+IGNvbGxlY3Rpb25fdGVtcCArIHNpemUgKyAoMXxzaXRlKWAuIFRoaXMgZXhhbWluZXMgdGhlIGVmZmVjdHMgb2YgdGVtcGVyYXR1cmUgYW5kIHNpemUgb24gQ1RtYXgsIHdpdGggcmFuZG9tIGludGVyY2VwdHMgZm9yIGVhY2ggc2l0ZS4gQm90aCBmaXhlZCBlZmZlY3RzIGhhdmUgYSBzaWduaWZpY2FudCBlZmZlY3Qgb24gQ1RtYXguIFRoZSBvdmVyYWxsIGVmZmVjdCBvZiB0ZW1wZXJhdHVyZSBzdWdnZXN0cyBhbiBpbmNyZWFzZSBpbiBDVG1heCBvZiAwLjE1wrBDIHBlciDCsEMgaW5jcmVhc2UgaW4gY29sbGVjdGlvbiB0ZW1wZXJhdHVyZSAoaS5lLiAtIGFuIEFSUiB2YWx1ZSBvZiAwLjE1KSwgd2hpbGUgaW5jcmVhc2luZyBib2R5IHNpemVzIGRlY3JlYXNlIENUbWF4IGJ5IDMuN8KwQyBwZXIgbW0gKG9yIGEgZGVjcmVhc2Ugb2YgfjAuMzfCsEMgcGVyIHRlbnRoIG9mIGEgbW0sIHdoaWNoIGlzIG1vcmUgYmlvbG9naWNhbGx5IHJlYWxpc3RpYyBmb3IgKkEuIHRvbnNhKikuIFRoaXMgQVJSIHZhbHVlIGlzIHNsaWdodGx5IGxvd2VyIHRoYW4gb2JzZXJ2ZWQgZm9yIG90aGVyIGNvcGVwb2Qgc3BlY2llcywgYnV0IHdlbGwgd2l0aGluIHRoZSByYW5nZSBvZiBwcmV2aW91c2x5IG9ic2VydmVkIHZhbHVlcy4gVGhlIGVzdGltYXRlZCBlZmZlY3Qgb2YgYm9keSBzaXplIGlzLCBhcyBleHBlY3RlZCwgc2ltaWxhciB0byB0aGF0IGZyb20gdGhlIHJlc2lkdWFscyBwbG90IGFib3ZlLiAKCmBgYHtyfQpjdG1heC5tb2RlbCA9IGxtZTQ6OmxtZXIoZGF0YSA9IGZpbHRlcmVkX2RhdGEsIAogICAgICAgICAgICAgICAgICAgICAgICAgY3RtYXggfiBjb2xsZWN0aW9uX3RlbXAgKyBzaXplICsgKDF8c2l0ZSkpCgplZmZlY3RzX3N1bW1hcnkgPSBkYXRhLmZyYW1lKCJUZW1wZXJhdHVyZSIgPSB1bm5hbWUobG1lNDo6Zml4ZWYoY3RtYXgubW9kZWwpWyJjb2xsZWN0aW9uX3RlbXAiXSksCiAgICAgICAgICAgIlNpemUiID0gdW5uYW1lKGxtZTQ6OmZpeGVmKGN0bWF4Lm1vZGVsKVsic2l6ZSJdKSkKCmtuaXRyOjprYWJsZShlZmZlY3RzX3N1bW1hcnkpCmBgYAoKQnkgZXh0cmFjdGluZyB0aGUgY29uZGl0aW9uYWwgbW9kZSBmb3IgdGhlIHJhbmRvbSBlZmZlY3RzLCB3ZSBjYW4gYWxzbyBleGFtaW5lIGhvdyB0aGVybWFsIGxpbWl0cyB2YXJ5IGFjcm9zcyBzaXRlcyBiZXlvbmQgdGhlIGluZmx1ZW5jZSBvZiBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlcyBhbmQgYm9keSBzaXplcy4gU2hvd24gYmVsb3cgYXJlIHRoZXNlIHZhbHVlcywgZXh0cmFjdGVkIGZyb20gdGhlIGxpbmVhciBtaXhlZCBlZmZlY3RzIG1vZGVsLiBXZSBjYW4gc2VlIHRoYXQsIHNpbWlsYXIgdG8gd2hhdCdzIGJlZW4gb2JzZXJ2ZWQgaW4gY29tbW9uIGdhcmRlbiBleHBlcmltZW50cyB3aXRoICpBLiB0b25zYSogcHJldmlvdXNseSwgY29wZXBvZHMgZnJvbSBzb3V0aGVybiBzaXRlcyBoYWQgaGlnaGVyIHRoZXJtYWwgbGltaXRzIHRoYW4gdGhvc2UgZnJvbSBub3J0aGVybiBzaXRlcy4gSW50ZXJlc3RpbmdseSwgdGhlc2UgcG9wdWxhdGlvbiBlZmZlY3RzIGluZGljYXRlIHRoYXQgbG93IHNhbGluaXR5IHNpdGVzIHRlbmRlZCB0byBoYXZlIGxvd2VyIHRoZXJtYWwgbGltaXRzIHRoYW4gdGhlaXIgcGFpcmVkIGhpZ2ggc2FsaW5pdHkgc2l0ZS4gCgpgYGB7ciBwb3AtZWZmcy1wbG90LCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD02fQpwb3BfZWZmcyA9IGFzLmRhdGEuZnJhbWUobG1lNDo6cmFuZWYoY3RtYXgubW9kZWwpKSAlPiUgCiAgc2VsZWN0KCJzaXRlIiA9IGdycCwgInBvcF9lZmYiID0gY29uZHZhbCwgInNkIiA9IGNvbmRzZCkgJT4lIAogIGlubmVyX2pvaW4oc2l0ZV9kYXRhLCBieSA9IGMoInNpdGUiKSkgJT4lIAogIG11dGF0ZShzaXRlID0gZmN0X3Jlb3JkZXIoc2l0ZSwgbGF0KSkKCmdncGxvdChwb3BfZWZmcywgYWVzKHggPSBsYXQsIHkgPSBwb3BfZWZmLCBjb2xvdXIgPSBzaXRlKSkgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IHBvcF9lZmYgLSBzZCwgeW1heCA9IHBvcF9lZmYgKyBzZCksCiAgICAgICAgICAgICAgICB3aWR0aCA9IDAuNSwgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeCA9ICJMYXRpdHVkZSIsIAogICAgICAgeSA9ICJQb3B1bGF0aW9uIEVmZmVjdCIpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmBgYAoKCiMjIFRyYWl0IFZhcmlhYmlsaXR5CgpTaG93biBiZWxvdyBpcyB0aGUgdHJhaXQgdmFyaWF0aW9uIChyYW5nZXMpIGZvciBlYWNoIHNpdGUuIFJhbmdlcyBhcmUgY2FsY3VsYXRlZCBmb3IgZWFjaCBjb2xsZWN0aW9uIHNlcGFyYXRlbHkuCgpgYGB7ciB0cmFpdC1yYW5nZS1wbG90fQp0cmFpdF9yYW5nZXMgPSBmdWxsX2RhdGEgJT4lIAogIGdyb3VwX2J5KHNpdGUsIHNlYXNvbiwgY29sbGVjdGlvbl90ZW1wLCBjb2xsZWN0aW9uX3NhbGluaXR5LCBkb3ksIGxhdCkgJT4lIAogIHN1bW1hcmlzZShtZWFuX2N0bWF4ID0gbWVhbihjdG1heCksCiAgICAgICAgICAgIGN0bWF4X3JhbmdlID0gbWF4KGN0bWF4KSAtIG1pbihjdG1heCksCiAgICAgICAgICAgIGN0bWF4X3ZhciA9IHZhcihjdG1heCksCiAgICAgICAgICAgIG1lYW5fc2l6ZSA9IG1lYW4oc2l6ZSksCiAgICAgICAgICAgIHNpemVfcmFuZ2UgPSBtYXgoc2l6ZSkgLSBtaW4oc2l6ZSksCiAgICAgICAgICAgIHNpemVfdmFyID0gdmFyKHNpemUpKSAlPiUgCiAgbXV0YXRlKHByb3BfY3RtYXhfcmFuZ2UgPSBjdG1heF9yYW5nZSAvIG1lYW5fY3RtYXgsCiAgICAgICAgIHByb3Bfc2l6ZV9yYW5nZSA9IHNpemVfcmFuZ2UgLyBtZWFuX3NpemUpCgpjdG1heF9yYW5nZV90ZW1wID0gZ2dwbG90KHRyYWl0X3JhbmdlcywgYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBjdG1heF9yYW5nZSwgY29sb3VyID0gc2l0ZSkpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggUmFuZ2UgKMKwQykiLAogICAgICAgeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpjdG1heF92YXJfdGVtcCA9IGdncGxvdCh0cmFpdF9yYW5nZXMsIGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gY3RtYXhfdmFyLCBjb2xvdXIgPSBzaXRlKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCBSYW5nZSAowrBDKSIsCiAgICAgICB4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCnNpemVfcmFuZ2VfdGVtcCA9IGdncGxvdCh0cmFpdF9yYW5nZXMsIGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gc2l6ZV9yYW5nZSwgY29sb3VyID0gc2l0ZSkpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiU2l6ZSBSYW5nZSAobW0pIiwKICAgICAgIHggPSAiQ29sbGVjdGlvbiBUZW1wLiAowrBDKSIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKc2l6ZV92YXJfdGVtcCA9IGdncGxvdCh0cmFpdF9yYW5nZXMsIGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gc2l6ZV92YXIsIGNvbG91ciA9IHNpdGUpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIlNpemUgUmFuZ2UgKG1tKSIsCiAgICAgICB4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmdnYXJyYW5nZShjdG1heF9yYW5nZV90ZW1wLCBzaXplX3JhbmdlX3RlbXAsIGNvbW1vbi5sZWdlbmQgPSBULCBsZWdlbmQgPSAiYm90dG9tIikKYGBgCgpDaGFuZ2VzIGluIHRyYWl0IHZhcmlhbmNlIG1heSBiZSBpbmRpY2F0aXZlIG9mIHBoZW5vdHlwaWMgc2VsZWN0aW9uLiBJZiBzZWxlY3Rpb24gKGFzIG9wcG9zZWQgdG8gYWNjbGltYXRpb24pIGFyZSBkcml2aW5nIHNlYXNvbmFsIGNoYW5nZXMsIHdlIG1heSBleHBlY3QgdG8gc2VlIGEgcmVkdWN0aW9uIGluIHZhcmlhbmNlIGluIHRoZSBwZWFrIHNhbXBsZXMgcmVsYXRpdmUgdG8gdGhlIGVhcmx5IHNlYXNvbiBzYW1wbGVzLiBOb3RlIHRoYXQgZWFybHkgc2Vhc29uIGNvbGxlY3Rpb24gdGVtcGVyYXR1cmVzIHRoaXMgeWVhciB3ZXJlIGhpZ2hlciB0aGFuIGV4cGVjdGVkLCBkcml2ZW4gYnkgZmFpcmx5IHN0cm9uZyBoZWF0d2F2ZXMgYWNyb3NzIHRoZSBOb3J0aCBBdGxhbnRpYy4gICAgCgpgYGB7ciBzZWFzb24tdmFyfQpnZ3Bsb3QodHJhaXRfcmFuZ2VzLCBhZXMoeCA9IHNlYXNvbiwgeSA9IGN0bWF4X3ZhciwgY29sb3VyID0gc2l0ZSkpICsgCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IHNpdGUpLCAKICAgICAgICAgICAgbGluZXdpZHRoID0gMS41KSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIkNUbWF4IFZhcmlhbmNlIiwKICAgICAgIHggPSAiU2Vhc29uIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIAogICAgICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IDAuMTI1KQpgYGAKCmBgYHtyIHZhci1jaGFuZ2UtdGVtcC1jaGFuZ2UsIGluY2x1ZGUgPSBGfQp2YXJfY2hhbmdlX2RhdGEgPSB0cmFpdF9yYW5nZXMgJT4lICAKICB1bmdyb3VwKCkgJT4lIAogIG11dGF0ZShtZWFuX3d0ID0gbWVhbl9jdG1heCAtIGNvbGxlY3Rpb25fdGVtcCkgJT4lIAogIGdyb3VwX2J5KHNpdGUpICU+JSAKICBhcnJhbmdlKHNpdGUsIGRveSkgJT4lICAKICBtdXRhdGUodGVtcF9jaGFuZ2UgPSBjb2xsZWN0aW9uX3RlbXAgLSBsYWcoY29sbGVjdGlvbl90ZW1wKSwKICAgICAgICAgY3RtYXhfY2hhbmdlID0gbWVhbl9jdG1heCAtIGxhZyhtZWFuX2N0bWF4KSwKICAgICAgICAgd3RfY2hhbmdlID0gbWVhbl93dCAtIGxhZyhtZWFuX3d0KSwKICAgICAgICAgdmFyX2NoYW5nZSA9IGN0bWF4X3ZhciAtIGxhZyhjdG1heF92YXIpKSAlPiUgIAogIHNlbGVjdChzaXRlLCBzZWFzb24sIGRveSwgbGF0LCB0ZW1wX2NoYW5nZSwgdmFyX2NoYW5nZSwgY3RtYXhfY2hhbmdlLCB3dF9jaGFuZ2UpCgpnZ3Bsb3QodmFyX2NoYW5nZV9kYXRhLCBhZXMoeCA9IHRlbXBfY2hhbmdlLCB5ID0gdmFyX2NoYW5nZSwgY29sb3VyID0gc2l0ZSkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiV2FybWluZyBUb2xlcmFuY2UgQ2hhbmdlICjCsEMpIiwKICAgICAgIHkgPSAiQ2hhbmdlIGluIENUbWF4IFZhcmlhbmNlIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICBsZWdlbmQudGl0bGUuYWxpZ24gPSAwLjEyNSkKCmdncGxvdCh0cmFpdF9yYW5nZXMsIGFlcyh4ID0gc2l6ZV9yYW5nZSwgeSA9IHNpemVfdmFyKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBnZW9tX3Ntb290aCgpICsKICB0aGVtZV9tYXR0KCkKYGBgCgojIyBDb21wYXJpbmcgcmF0ZXMgb2YgY2hhbmdlIChIYWxkYW5lcykKQm90aCBDVG1heCBhbmQgYm9keSBzaXplIHZhcmllZCBiZXR3ZWVuIHNpdGVzIGFuZCBhY3Jvc3Mgc2Vhc29ucy4gSXQgY2FuIGJlIGRpZmZpY3VsdCB0byBkaXJlY3RseSBjb21wYXJlIHRoZXNlIHR3byB0cmFpdHMuIFdlIHRha2UgdHdvIGFwcHJvYWNoZXMgdG8gZWFzZSB0aGlzIGNvbXBhcmlzb24uIApTaG93biBiZWxvdyBpcyBhIGNvbXBhcmlzb24gb2YgdGhlIHNsb3BlcyBmcm9tIHRoZSB0cmFpdCByZWdyZXNzaW9ucyBhZ2FpbnN0IGNvbGxlY3Rpb24gdGVtcGVyYXR1cmUgZm9yIGVhY2ggcG9wdWxhdGlvbiwgc3RhbmRhcmRpemVkIGJ5IHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIHRyYWl0IGZvciBlYWNoIHBvcHVsYXRpb24gKGFjcm9zcyBhbGwgY29sbGVjdGlvbnMpLiBUaGlzIHByZXNlbnRzIGNoYW5nZSBwZXIgZGVncmVlIGNoYW5nZSBpbiBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlIGluIHVuaXRzIG9mIHN0YW5kYXJkIGRldmlhdGlvbnMgZm9yIGJvdGggQ1RtYXggYW5kIGJvZHkgc2l6ZS4KCmBgYHtyIGFkai1zbG9wZS1jb21wLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD02fQphZGpfc2xvcGVzID0gZnVsbF9kYXRhICU+JSAKICBncm91cF9ieShzaXRlLCBsYXQpICU+JSAKICBhcnJhbmdlKGRveSkgJT4lICAKICBmaWx0ZXIoc2l0ZSAhPSAiS2V5IExhcmdvIikgJT4lCiAgc3VtbWFyaXplKCJjdG1heF9zbG9wZSIgPSBjb2VmKGxtKGN0bWF4IH4gY29sbGVjdGlvbl90ZW1wKSlbImNvbGxlY3Rpb25fdGVtcCJdLCAKICAgICAgICAgICAgIm1lYW5fY3RtYXgiID0gbWVhbihjdG1heCksCiAgICAgICAgICAgICJjdG1heF9zZCIgPSBzZChjdG1heCksCiAgICAgICAgICAgICJzaXplX3Nsb3BlIiA9IGNvZWYobG0oc2l6ZSB+IGNvbGxlY3Rpb25fdGVtcCkpWyJjb2xsZWN0aW9uX3RlbXAiXSwgCiAgICAgICAgICAgICJtZWFuX3NpemUiID0gbWVhbihzaXplKSwKICAgICAgICAgICAgInNpemVfc2QiID0gc2Qoc2l6ZSksIAogICAgICAgICAgICAidGVtcF9yYW5nZSIgPSBtYXgoY29sbGVjdGlvbl90ZW1wKSAtIG1pbihjb2xsZWN0aW9uX3RlbXApKSAlPiUgIAogIGRyb3BfbmEoKSAlPiUgCiAgbXV0YXRlKGFkal9jdG1heF9zbG9wZSA9IGN0bWF4X3Nsb3BlIC8gY3RtYXhfc2QsCiAgICAgICAgIGFkal9zaXplX3Nsb3BlID0gc2l6ZV9zbG9wZSAvIHNpemVfc2QpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGNvbnRhaW5zKCJfc2xvcGUiKSwgCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInNsb3BlX3R5cGUiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAic2xvcGUiKQoKIyBnZ3Bsb3QoYWRqX3Nsb3BlcywgYWVzKHggPSBsYXQsIHkgPSB0ZW1wX3JhbmdlKSkgKyAKIyAgIGdlb21fcG9pbnQoKSArIAojICAgdGhlbWVfbWF0dCgpCgpnZ3Bsb3QoZmlsdGVyKGFkal9zbG9wZXMsIHN0cl9kZXRlY3Qoc2xvcGVfdHlwZSwgImFkal8iKSksIGFlcyh4ID0gc2xvcGVfdHlwZSwgeSA9IGFicyhzbG9wZSksIAogICAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gc2l0ZSwgY29sb3VyID0gc2l0ZSkpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKyAKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiIiwgCiAgICAgICB5ID0gIlNsb3BlIChhYnNvbHV0ZSB2YWx1ZSkiKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMDAsIGhqdXN0ID0gMCwgdmp1c3QgPSAwLjUpKQpgYGAKCkhhbGRhbmVzIGFyZSBhIHNpbWlsYXIgdW5pdCwgcmVwcmVzZW50aW5nIGNoYW5nZSBpbiB1bml0cyBvZiBzdGFuZGFyZCBkZXZpYXRpb25zIHBlciBnZW5lcmF0aW9uLiBUaGlzIGNhbiBiZSBhIHVzZWZ1bCBtZXRyaWMgZm9yIGNvbXBhcmluZyBhY3Jvc3MgdHJhaXRzLCBlc3BlY2lhbGx5IGFzIHRoZSBudW1iZXIgb2YgZ2VuZXJhdGlvbnMgY292ZXJlZCBieSBvdXIgc2FtcGxpbmcgcGVyaW9kIGxpa2VseSB2YXJpZXMgYWNyb3NzIHBvcHVsYXRpb25zLiBUaGUgY2FsY3VsYXRpb24gb2YgaGFsZGFuZXMgaXMgdGFrZW4gZnJvbSBIZW5kcnkgYW5kIEtpbm5pc29uICgxOTk5KSwgd2hpY2ggaW4gdHVybiBpcyBiYXNlZCBvbiB3b3JrIGZyb20gR2luZ2VyaWNoICgxOTkzKS4gV2UgZXN0aW1hdGVkIHRoZSBudW1iZXIgb2YgZ2VuZXJhdGlvbnMgcGFzc2VkIGJldHdlZW4gY29sbGVjdGlvbnMgdXNpbmcgdGhlIGVtcGlyaWNhbCByZWxhdGlvbnNoaXAgYmV0d2VlbiB0ZW1wZXJhdHVyZSBhbmQgZGV2ZWxvcG1lbnQgdGltZSBmb3IgKkFjYXJ0aWEgdG9uc2EqIGZyb20gTGVhbmRybyBldCBhbC4gKDIwMDYpLiBGb3IgaW5pdGlhbCBlc3RpbWF0ZXMsIHdlIHVzZWQgYSB0ZW1wZXJhdHVyZSBoYWxmd2F5IGJldHdlZW4gd2hhdCB3YXMgb2JzZXJ2ZWQgZHVyaW5nIGNvbGxlY3Rpb24uIENoYW5nZXMgd2VyZSBleGFtaW5lZCBmb3IgZWFjaCBwYWlyIG9mIGNvbGxlY3Rpb25zIChlYXJseSB0byBwZWFrLCBhbmQgcGVhayB0byBsYXRlKS4gICAgCgpTaG93biBiZWxvdyBpcyBhIGNvbXBhcmlzb24gb2YgdGhlIGVzdGltYXRlZCBoYWxkYW5lIHZhbHVlcyBmb3IgQ1RtYXggYW5kIGJvZHkgc2l6ZSwgc2VwYXJhdGVkIGJ5IHNlYXNvbi4gS2VlcCBpbiBtaW5kIHRoYXQgd2hpbGUgdGhpcyBtZXRyaWMgYWNjb3VudHMgZm9yIGRpZmZlcmVuY2VzIGluIHRoZSBudW1iZXIgb2YgZ2VuZXJhdGlvbnMgYmV0d2VlbiBjb2xsZWN0aW9ucywgaXQgZG9lcyBub3QgZGlyZWN0bHkgYWNjb3VudCBmb3IgZGlmZmVyZW5jZXMgaW4gdGVtcGVyYXR1cmUsIGxlYWRpbmcgdG8gaW5mbGF0ZWQgdmFsdWVzIGluIHRoZSAicGVhayB0byBsYXRlIiBjb21wYXJpc29ucywgd2hpY2ggdHlwaWNhbGx5IGNvdmVyZWQgYSBsYXJnZXIgcmFuZ2Ugb2YgdGVtcGVyYXR1cmVzLiAKCmBgYHtyIGhhbGRhbmUtY29tcC1wbG90LCBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTl9CmVhcmx5X3BlYWsgPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzZWFzb24gJWluJSBjKCJlYXJseSIsICJwZWFrIikpICU+JSAKICBtdXRhdGUoc2Vhc29uID0gaWZfZWxzZShzZWFzb24gPT0gImVhcmx5IiwgIm9uZSIsICJ0d28iKSkgJT4lIAogIGdyb3VwX2J5KHNpdGUpICU+JSAKICBtdXRhdGUoY3RtYXhfc2RfcCA9IHNkKGN0bWF4KSwKICAgICAgICAgc2l6ZV9zZF9wID0gc2Qoc2l6ZSksIAogICAgICAgICB0ZW1wX2NoYW5nZSA9IG1heChjb2xsZWN0aW9uX3RlbXApIC0gbWluKGNvbGxlY3Rpb25fdGVtcCksCiAgICAgICAgIGF2Z190ZW1wID0gKG1heChjb2xsZWN0aW9uX3RlbXApICsgbWluKGNvbGxlY3Rpb25fdGVtcCkpIC8gMiwKICAgICAgICAgZGF5c19wYXNzZWQgPSBtYXgoZG95KSAtIG1pbihkb3kpKSAlPiUgCiAgc2VsZWN0KHNpdGUsIGxhdCwgc2Vhc29uLCAKICAgICAgICAgY3RtYXhfc2RfcCwgc2l6ZV9zZF9wLCAKICAgICAgICAgdGVtcF9jaGFuZ2UsIGF2Z190ZW1wLCBkYXlzX3Bhc3NlZCwgCiAgICAgICAgIGN0bWF4LCBzaXplKSAlPiUKICBncm91cF9ieShzaXRlLCBsYXQsIHNlYXNvbiwgCiAgICAgICAgICAgY3RtYXhfc2RfcCwgc2l6ZV9zZF9wLCAKICAgICAgICAgICB0ZW1wX2NoYW5nZSwgYXZnX3RlbXAsIGRheXNfcGFzc2VkKSAlPiUgCiAgc3VtbWFyaXplKGN0bWF4ID0gbWVhbihjdG1heCksCiAgICAgICAgICAgIHNpemUgPSBtZWFuKHNpemUpKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoc2l0ZSwgbGF0LCBjdG1heF9zZF9wLCBzaXplX3NkX3AsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRlbXBfY2hhbmdlLCBhdmdfdGVtcCwgZGF5c19wYXNzZWQpLCAKICAgICAgICAgICAgICBuYW1lc19mcm9tID0gc2Vhc29uLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGMoY3RtYXgsIHNpemUpKSAlPiUgCiAgbXV0YXRlKHNlYXNvbiA9ICJlYXJseV90b19wZWFrIikgJT4lICAKICBkcm9wX25hKCkKCnBlYWtfbGF0ZSA9IGZ1bGxfZGF0YSAlPiUgCiAgZmlsdGVyKHNlYXNvbiAlaW4lIGMoInBlYWsiLCAibGF0ZSIpKSAlPiUgCiAgbXV0YXRlKHNlYXNvbiA9IGlmX2Vsc2Uoc2Vhc29uID09ICJwZWFrIiwgIm9uZSIsICJ0d28iKSkgJT4lIAogIGdyb3VwX2J5KHNpdGUpICU+JSAKICBtdXRhdGUoY3RtYXhfc2RfcCA9IHNkKGN0bWF4KSwKICAgICAgICAgc2l6ZV9zZF9wID0gc2Qoc2l6ZSksIAogICAgICAgICB0ZW1wX2NoYW5nZSA9IGxhc3QoY29sbGVjdGlvbl90ZW1wKSAtIGZpcnN0KGNvbGxlY3Rpb25fdGVtcCksCiAgICAgICAgIGF2Z190ZW1wID0gKG1heChjb2xsZWN0aW9uX3RlbXApICsgbWluKGNvbGxlY3Rpb25fdGVtcCkpIC8gMiwKICAgICAgICAgZGF5c19wYXNzZWQgPSBtYXgoZG95KSAtIG1pbihkb3kpKSAlPiUgCiAgc2VsZWN0KHNpdGUsIGxhdCwgc2Vhc29uLCBjdG1heF9zZF9wLCBzaXplX3NkX3AsIAogICAgICAgICB0ZW1wX2NoYW5nZSwgYXZnX3RlbXAsIGRheXNfcGFzc2VkLCAKICAgICAgICAgY3RtYXgsIHNpemUpICU+JQogIGdyb3VwX2J5KHNpdGUsIGxhdCwgc2Vhc29uLCBjdG1heF9zZF9wLCBzaXplX3NkX3AsIAogICAgICAgICAgIHRlbXBfY2hhbmdlLCBhdmdfdGVtcCwgZGF5c19wYXNzZWQpICU+JSAKICBzdW1tYXJpemUoY3RtYXggPSBtZWFuKGN0bWF4KSwKICAgICAgICAgICAgc2l6ZSA9IG1lYW4oc2l6ZSkpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhzaXRlLCBsYXQsIGN0bWF4X3NkX3AsIHNpemVfc2RfcCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGVtcF9jaGFuZ2UsIGF2Z190ZW1wLCBkYXlzX3Bhc3NlZCksIAogICAgICAgICAgICAgIG5hbWVzX2Zyb20gPSBzZWFzb24sIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYyhjdG1heCwgc2l6ZSkpICU+JSAKICBtdXRhdGUoc2Vhc29uID0gInBlYWtfdG9fbGF0ZSIpICU+JSAgCiAgZHJvcF9uYSgpCgpjYWxjX2hhbGRzID0gZnVuY3Rpb24oeDEsIHgyLCBzZF9wLCBnKXsKICAoKHgyIC8gc2RfcCkgLSAoeDEgLyBzZF9wKSkgLyBnCn0KCmhhbGRhbmVzID0gYmluZF9yb3dzKGVhcmx5X3BlYWssIHBlYWtfbGF0ZSkgJT4lIAogIG11dGF0ZSgiZ2VuX3RpbWUiID0gNTQ5MCooYXZnX3RlbXAgKyAxKV4tMi4wNSwgCiAgICAgICAgICJnZW5zIiA9IGZsb29yKGRheXNfcGFzc2VkIC8gZ2VuX3RpbWUpLAogICAgICAgICAiY3RtYXhfaGFsZGFuZXMiID0gY2FsY19oYWxkcyh4MiA9IGN0bWF4X3R3bywgeDEgPSBjdG1heF9vbmUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZF9wID0gY3RtYXhfc2RfcCwgZyA9IGdlbnMpLAogICAgICAgICAic2l6ZV9oYWxkYW5lcyIgPSBjYWxjX2hhbGRzKHgyID0gc2l6ZV90d28sIHgxID0gc2l6ZV9vbmUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkX3AgPSBzaXplX3NkX3AsIGcgPSBnZW5zKSkKCmhhbGRhbmVzICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHNlbGVjdChzaXRlLCB0ZW1wX2NoYW5nZSwgc2Vhc29uLCBjdG1heF9oYWxkYW5lcywgc2l6ZV9oYWxkYW5lcykgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gYyhjdG1heF9oYWxkYW5lcywgc2l6ZV9oYWxkYW5lcyksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gYygidHlwZSIsIE5BKSwgCiAgICAgICAgICAgICAgIG5hbWVzX3NlcCA9ICJfIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gImhhbGRhbmVzIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHR5cGUsIHkgPSBoYWxkYW5lcywgZ3JvdXAgPSBzaXRlLCBjb2xvdXIgPSBzaXRlKSkgKyAKICBmYWNldF93cmFwKHNlYXNvbn4uKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9saW5lKGFlcyhsaW5ld2lkdGggPSBkZXNjKHRlbXBfY2hhbmdlKSkpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh4ID0gIlRyYWl0IiwgCiAgICAgICB5ID0gIkhhbGRhbmVzIiwgCiAgICAgICBsaW5ld2lkdGggPSAiVGVtcC4gQ2hhbmdlIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpCmBgYAoKU2hvd24gYmVsb3cgYXJlIHRoZSBoYWxkYW5lIHZhbHVlcyBwbG90dGVkIGFnYWluc3QgbGF0aXR1ZGUuIE5vdGUgdGhhdCBldmVuIHRob3VnaCBsYXJnZSBjaGFuZ2VzIGluIHRlbXBlcmF0dXJlIG9jY3VyZWQgYmV0d2VlbiBwZWFrIGFuZCBsYXRlIHNhbXBsZXMgaW4gdGhlIENoZXNhcGVha2UsIHRoZSBjaGFuZ2UgaW4gaGFsZGFuZXMgaXMgcmVsYXRpdmVseSBzbWFsbCwgd2hpbGUgaW4gdGhlIE5vcnRoZXJuIHBvcHVsYXRpb25zLCBjaGFuZ2VzIGFyZSBsYXJnZXIsIHRob3VnaCBtb3JlIHZhcmlhYmxlLiAKCmBgYHtyIGhhbGRhbmVzLWxhdC1wbG90LCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9OH0KY3RtYXhfaGFsZGFuZXMgPSBnZ3Bsb3QoaGFsZGFuZXMsIGFlcyh4ID0gbGF0LCB5ID0gY3RtYXhfaGFsZGFuZXMsIGNvbG91ciA9IHNpdGUsIHNoYXBlID0gc2Vhc29uKSkgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh4ID0gIkxhdGl0dWRlIiwKICAgICAgIHkgPSAiQ2hhbmdlIGluIENUbWF4IChoYWxkYW5lcykiKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKCkKCnNpemVfaGFsZGFuZXMgPSBnZ3Bsb3QoaGFsZGFuZXMsIGFlcyh4ID0gbGF0LCB5ID0gc2l6ZV9oYWxkYW5lcywgY29sb3VyID0gc2l0ZSwgc2hhcGUgPSBzZWFzb24pKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiTGF0aXR1ZGUiLAogICAgICAgeSA9ICJDaGFuZ2UgaW4gU2l6ZSAoaGFsZGFuZXMpIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpCgpnZ2FycmFuZ2UoY3RtYXhfaGFsZGFuZXMsIHNpemVfaGFsZGFuZXMsIGNvbW1vbi5sZWdlbmQgPSBULCBsZWdlbmQgPSAicmlnaHQiLCBucm93ID0gMikKYGBgCgoKIyMgTmV4dCBTdGVwcwoKQWZ0ZXIgcGhlbm90eXBpbmcsIGVhY2ggaW5kaXZpZHVhbCB3YXMgcHJlc2VydmVkIGluIDk1JSBldGhhbm9sLiBJbmRpdmlkdWFsIEROQSBsaWJyYXJpZXMgd2lsbCBiZSBwcmVwYXJlZCB1c2luZyBUd2lzdCBCaW8gOTYtcGxleCBwcmVwIGtpdHMsIHRoZW4gc2VxdWVuY2VkIG9uIGFuIElsbHVtaW5hIE5vdmFTZXEgWCBQbHVzLiBVc2luZyB0aGUgbG93LWNvdmVyYWdlIHdob2xlIGdlbm9tZSBzZXF1ZW5jZXMsIHdlIHdpbGwgZXhhbWluZSBzZWFzb25hbCBwYXR0ZXJucyBpbiBhbGxlbGUgZnJlcXVlbmN5IGNoYW5nZSwgYW5kIGNvbXBhcmUgdGhlc2UgZmluZSBzY2FsZSB0ZW1wb3JhbCBwYXR0ZXJucyB3aXRoIHRoZSBsYXJnZXIgbGF0aXR1ZGluYWwgcGF0dGVybnMgaW4gYWxsZWxlIGZyZXF1ZW5jeSB0byBkZXRlcm1pbmUgd2hldGhlciB0aGUgc2FtZSBhbGxlbGVzIGRyaXZpbmcgcmFwaWQgc2Vhc29uYWwgYWRhcHRhdGlvbiBhcmUgaW4gcGxheSBvdmVyIGxhcmdlciBzcGF0aWFsIChhbmQgbG9uZ2VyIHRlbXBvcmFsKSBzY2FsZXMuCgojIyBNaXNjLiBEZXRhaWxzCgpgYGB7ciB0ZW1wLXJlY29yZC1wbG90LCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD02fQpnZ3Bsb3QodGVtcF9yZWNvcmQsIGFlcyh4ID0gbWludXRlX3Bhc3NlZCwgeSA9IHRlbXBfQywgZ3JvdXAgPSBmYWN0b3IocnVuKSkpICsgCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAwLjMsIGludGVyY2VwdCA9IG1lYW4odGVtcF9yZWNvcmRbdGVtcF9yZWNvcmQkbWludXRlX2ludGVydmFsID09IDAsIDhdKSkgKyAKICBnZW9tX2FibGluZShzbG9wZSA9IDAuMSwgaW50ZXJjZXB0ID0gbWVhbih0ZW1wX3JlY29yZFt0ZW1wX3JlY29yZCRtaW51dGVfaW50ZXJ2YWwgPT0gMCwgOF0pKSArIAogIGdlb21fbGluZShsaW5ld2lkdGggPSAwLjIsIGFscGhhID0gMC44KSArIAogIGdlb21fcG9pbnQoZGF0YSA9IGZ1bGxfZGF0YSwgCiAgICAgICAgICAgICBhZXMoeCA9IHRpbWUsIHkgPSBjdG1heCArIDAuNCksCiAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgIHNoYXBlID0gMjUpICsKICBsYWJzKHggPSAiVGltZSBwYXNzZWQgKG1pbnV0ZXMpIiwKICAgICAgIHkgPSAiVGVtcGVyYXR1cmUgKGRlZ3JlZXMgQykiLAogICAgICAgZmlsbCA9ICJUcmlhbCBOdW1iZXIiKSArIAogIGd1aWRlcyhjb2xvdXIgPSAibm9uZSIpICsgCiAgdGhlbWVfbWF0dChiYXNlX3NpemUgPSAxNikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCmBgYHtyIHJhbXAtcmVjb3JkLXBsb3QsIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTZ9CnJhbXBfcmVjb3JkMiA9IHJhbXBfcmVjb3JkICU+JSAKICBncm91cF9ieShydW4sIG1pbnV0ZV9pbnRlcnZhbCkgJT4lIAogIHN1bW1hcmlzZShtZWFuX3JhbXAgPSBtZWFuKHJhbXBfcGVyX21pbnV0ZSkpICU+JSAKICB1bmdyb3VwKCkKCmdncGxvdChyYW1wX3JlY29yZDIsIGFlcyh4ID0gbWludXRlX2ludGVydmFsLCB5ID0gbWVhbl9yYW1wKSkgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjMpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC4xKSArIAogICNnZW9tX3BvaW50KCkgKyAKICBnZW9tX2hleChiaW5zID0gMzApICsgCiAgeWxpbSgwLCAwLjM1KSArIAogIGxhYnMoeSA9ICJSYW1wIFJhdGUgKGRlZy4gQyAvIG1pbi4pIiwKICAgICAgIHggPSAiVGltZSBpbnRvIHJ1biAobWludXRlKSIpICsgCiAgdGhlbWVfbWF0dChiYXNlX3NpemUgPSAxNikgCmBgYAoKYGBge3IgcmVwLWNvbXAsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD04fQpmdWxsX2RhdGEgJT4lIAogIGRyb3BfbmEocmVwbGljYXRlKSAlPiUgIAogIGdncGxvdChhZXMoeCA9IGZhY3RvcihyZXBsaWNhdGUpLCB5ID0gY3RtYXgsIGdyb3VwID0gc2l0ZSkpICsgCiAgZmFjZXRfZ3JpZChzaXRlfnNlYXNvbiwgc2NhbGVzID0gImZyZWVfeSIpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMSwgaGVpZ2h0ID0gMCksCiAgICAgICAgICAgICBhbHBoYSA9IDAuNCwKICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5MzAiKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG91ciA9ICJibGFjayIpICsgCiAgbGFicyh4ID0gIlJlcGxpY2F0ZSIsIAogICAgICAgeSA9ICJDVG1heCIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoKQpgYGAKCmBgYHtyIG51bS1nZW5zLXBsb3QsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD03fQpnZ3Bsb3QoaGFsZGFuZXMsIGFlcyh4ID0gbGF0LCB5ID0gZ2VucywgY29sb3VyID0gc2l0ZSwgc2hhcGUgPSBzZWFzb24pKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9wb2ludChzaXplID0gNSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiTGF0aXR1ZGUiLCAKICAgICAgIHkgPSAiR2VuZXJhdGlvbnMgYmV0d2VlbiBcbmNvbGxlY3Rpb25zIikgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoZnJvbSA9IDAsIHRvID0gMTEsIGJ5ID0gMikpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgo=